1
0
mirror of git://projects.qi-hardware.com/openwrt-xburst.git synced 2024-11-24 02:34:06 +02:00

lantiq: bump to 3.1

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@28721 3c298f89-4303-0410-b956-a3cf2f4a3e73
This commit is contained in:
blogic 2011-11-03 15:15:52 +00:00
parent de6080b7c2
commit dfffaea839
113 changed files with 1072 additions and 47364 deletions

View File

@ -12,7 +12,7 @@ BOARDNAME:=Lantiq GPON/XWAY
FEATURES:=squashfs jffs2
DEFAULT_SUBTARGET:=danube
LINUX_VERSION:=3.0.3
LINUX_VERSION:=3.1
CFLAGS=-Os -pipe -mips32r2 -mtune=mips32r2 -fno-caller-saves

View File

@ -68,7 +68,7 @@ define Profile/ARV7525PW
kmod-rt2800-pci wpad-mini kmod-ltq-dsl-firmware-b-danube
endef
define Profile/ARV4525PW/Description
define Profile/ARV7525PW/Description
Package set optimized for the ARV4525PW
endef

View File

@ -1,109 +0,0 @@
/*
* 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.
*
* Copyright (C) 2011 Andrej Vlašić
* Copyright (C) 2011 Luka Perkov
*
*/
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <linux/gpio.h>
#include <linux/gpio_buttons.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
#include <linux/input.h>
#include <linux/ath5k_platform.h>
#include <linux/pci.h>
#include <linux/phy.h>
#include <irq.h>
#include <lantiq_soc.h>
#include <lantiq_platform.h>
#include "../machtypes.h"
#include "../dev-leds-gpio.h"
#include "devices.h"
#include "dev-dwc_otg.h"
static struct mtd_partition gigasx76x_partitions[] =
{
{
.name = "secondary_env",
.offset = 0xe000,
.size = 0x2000,
},
{
.name = "secondary_boot",
.offset = 0x10000,
.size = 0x10000,
},
{
.name = "uboot",
.offset = 0x20000,
.size = 0x30000,
},
{
.name = "linux",
.offset = 0x50000,
.size = 0x7a0000,
},
{
.name = "board_config",
.offset = 0x7f0000,
.size = 0x10000,
},
};
static struct gpio_led
gigasx76x_leds_gpio[] __initdata = {
{ .name = "soc:green:usb", .gpio = 202, },
{ .name = "soc:green:wlan", .gpio = 203, },
{ .name = "soc:green:phone2", .gpio = 204, },
{ .name = "soc:green:phone1", .gpio = 205, },
{ .name = "soc:green:line", .gpio = 206, },
{ .name = "soc:green:online", .gpio = 207, },
};
static struct physmap_flash_data gigasx76x_flash_data = {
.nr_parts = ARRAY_SIZE(gigasx76x_partitions),
.parts = gigasx76x_partitions,
};
static struct ltq_pci_data ltq_pci_data = {
.clock = PCI_CLOCK_INT,
.gpio = PCI_GNT1 | PCI_REQ1,
.irq = {
[14] = INT_NUM_IM0_IRL0 + 22,
},
};
static struct ltq_eth_data ltq_eth_data = {
.mii_mode = PHY_INTERFACE_MODE_MII,
};
static void __init
gigasx76x_init(void)
{
#define GIGASX76X_USB 29
ltq_register_gpio_stp();
ltq_register_nor(&gigasx76x_flash_data);
ltq_register_pci(&ltq_pci_data);
ltq_register_etop(&ltq_eth_data);
xway_register_dwc(GIGASX76X_USB);
ltq_register_tapi();
ltq_register_madwifi_eep();
ltq_add_device_leds_gpio(-1, ARRAY_SIZE(gigasx76x_leds_gpio), gigasx76x_leds_gpio);
}
MIPS_MACHINE(LANTIQ_MACH_GIGASX76X,
"GIGASX76X",
"GIGASX76X - Gigaset SX761,SX762,SX763",
gigasx76x_init);

View File

@ -14,8 +14,8 @@
#include <linux/leds.h>
void ltq_add_device_leds_gpio(int id,
unsigned num_leds,
struct gpio_led *leds) __init;
void ltq_add_device_gpio_leds(int id,
unsigned num_leds,
struct gpio_led *leds) __init;
#endif /* _LANTIQ_DEV_LEDS_GPIO_H */

View File

@ -9,11 +9,11 @@
* by the Free Software Foundation.
*/
#include "linux/init.h"
#include "linux/slab.h"
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include "dev-gpio-buttons.h"
#include <dev-gpio-buttons.h>
void __init ltq_register_gpio_keys_polled(int id,
unsigned poll_interval,

View File

@ -15,9 +15,9 @@
#include <linux/slab.h>
#include <linux/platform_device.h>
#include "dev-leds-gpio.h"
#include <dev-gpio-leds.h>
void __init ltq_add_device_leds_gpio(int id, unsigned num_leds,
void __init ltq_add_device_gpio_leds(int id, unsigned num_leds,
struct gpio_led *leds)
{
struct platform_device *pdev;
@ -31,7 +31,7 @@ void __init ltq_add_device_leds_gpio(int id, unsigned num_leds,
memcpy(p, leds, num_leds * sizeof(*p));
pdev = platform_device_alloc("leds-gpio", id);
pdev = platform_device_alloc("gpio-leds", id);
if (!pdev)
goto err_free_leds;

View File

@ -1,10 +1,11 @@
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/i2c-gpio.h>
#include "../machtypes.h"
#include <dev-gpio-leds.h>
#include "../machtypes.h"
#include "devices.h"
#include "dev-leds-gpio.h"
#define BOARD_95C3AM1_GPIO_LED_0 10
#define BOARD_95C3AM1_GPIO_LED_1 11
@ -47,7 +48,7 @@ static struct spi_board_info board_95C3AM1_flash_data __initdata = {
.platform_data = &board_95C3AM1_flash_platform_data
};
static struct gpio_led board_95C3AM1_leds_gpio[] __initdata = {
static struct gpio_led board_95C3AM1_gpio_leds[] __initdata = {
{
.name = "power",
.gpio = BOARD_95C3AM1_GPIO_LED_0,
@ -85,8 +86,8 @@ static void __init board_95C3AM1_init(void)
falcon_register_i2c();
falcon_register_spi_flash(&board_95C3AM1_flash_data);
platform_device_register(&board_95C3AM1_i2c_gpio_device);
ltq_add_device_leds_gpio(-1, ARRAY_SIZE(board_95C3AM1_leds_gpio),
board_95C3AM1_leds_gpio);
ltq_add_device_gpio_leds(-1, ARRAY_SIZE(board_95C3AM1_gpio_leds),
board_95C3AM1_gpio_leds);
}
MIPS_MACHINE(LANTIQ_MACH_95C3AM1,

View File

@ -10,9 +10,10 @@
#include <linux/spi/spi.h>
#include <linux/spi/flash.h>
#include <dev-gpio-leds.h>
#include "../machtypes.h"
#include "devices.h"
#include "dev-leds-gpio.h"
#define EASY98020_GPIO_LED_0 9
#define EASY98020_GPIO_LED_1 10
@ -59,7 +60,7 @@ static struct spi_board_info easy98020_spi_flash_data __initdata = {
.platform_data = &easy98020_spi_flash_platform_data
};
static struct gpio_led easy98020_leds_gpio[] __initdata = {
static struct gpio_led easy98020_gpio_leds[] __initdata = {
{
.name = "easy98020:green:0",
.gpio = EASY98020_GPIO_LED_0,
@ -99,8 +100,8 @@ static void __init easy98020_init(void)
{
falcon_register_i2c();
falcon_register_spi_flash(&easy98020_spi_flash_data);
ltq_add_device_leds_gpio(-1, ARRAY_SIZE(easy98020_leds_gpio),
easy98020_leds_gpio);
ltq_add_device_gpio_leds(-1, ARRAY_SIZE(easy98020_gpio_leds),
easy98020_gpio_leds);
}
MIPS_MACHINE(LANTIQ_MACH_EASY98020,

View File

@ -21,9 +21,9 @@
#include <lantiq_soc.h>
#include <lantiq_platform.h>
#include <dev-gpio-leds.h>
#include "../machtypes.h"
#include "../dev-leds-gpio.h"
#include "devices.h"
#include "dev-dwc_otg.h"
@ -75,6 +75,30 @@ static struct mtd_partition arv45xx_partitions[] =
},
};
static struct mtd_partition arv7525_partitions[] =
{
{
.name = "uboot",
.offset = 0x0,
.size = 0x10000,
},
{
.name = "uboot_env",
.offset = 0x10000,
.size = 0x10000,
},
{
.name = "linux",
.offset = 0x20000,
.size = 0x3d0000,
},
{
.name = "board_config",
.offset = 0x3f0000,
.size = 0x10000,
},
};
static struct mtd_partition arv75xx_partitions[] =
{
{
@ -109,6 +133,11 @@ static struct physmap_flash_data arv45xx_flash_data = {
.parts = arv45xx_partitions,
};
static struct physmap_flash_data arv7525_flash_data = {
.nr_parts = ARRAY_SIZE(arv7525_partitions),
.parts = arv7525_partitions,
};
static struct physmap_flash_data arv75xx_flash_data = {
.nr_parts = ARRAY_SIZE(arv75xx_partitions),
.parts = arv75xx_partitions,
@ -127,12 +156,12 @@ static struct ltq_eth_data ltq_eth_data = {
};
static struct gpio_led
arv4510pw_leds_gpio[] __initdata = {
arv4510pw_gpio_leds[] __initdata = {
{ .name = "soc:green:foo", .gpio = 4, .active_low = 1, },
};
static struct gpio_led
arv4518pw_leds_gpio[] __initdata = {
arv4518pw_gpio_leds[] __initdata = {
{ .name = "soc:green:power", .gpio = 3, .active_low = 1, .default_trigger = "default-on" },
{ .name = "soc:green:adsl", .gpio = 4, .active_low = 1, .default_trigger = "default-on" },
{ .name = "soc:green:internet", .gpio = 5, .active_low = 1, .default_trigger = "default-on" },
@ -154,7 +183,7 @@ arv4518pw_gpio_buttons[] __initdata = {
};
static struct gpio_led
arv4520pw_leds_gpio[] __initdata = {
arv4520pw_gpio_leds[] __initdata = {
{ .name = "soc:blue:power", .gpio = 3, .active_low = 1, },
{ .name = "soc:blue:adsl", .gpio = 4, .active_low = 1, },
{ .name = "soc:blue:internet", .gpio = 5, .active_low = 1, },
@ -171,7 +200,7 @@ arv4520pw_leds_gpio[] __initdata = {
};
static struct gpio_led
arv452cpw_leds_gpio[] __initdata = {
arv452cpw_gpio_leds[] __initdata = {
{ .name = "soc:blue:power", .gpio = 3, .active_low = 1, .default_trigger = "default-on" },
{ .name = "soc:blue:adsl", .gpio = 4, .active_low = 1, .default_trigger = "default-on" },
{ .name = "soc:blue:isdn", .gpio = 5, .active_low = 1, .default_trigger = "default-on" },
@ -190,7 +219,7 @@ arv452cpw_leds_gpio[] __initdata = {
};
static struct gpio_led
arv4525pw_leds_gpio[] __initdata = {
arv4525pw_gpio_leds[] __initdata = {
{ .name = "soc:green:festnetz", .gpio = 4, .active_low = 1, .default_trigger = "default-on" },
{ .name = "soc:green:internet", .gpio = 5, .active_low = 1, .default_trigger = "default-on" },
{ .name = "soc:green:dsl", .gpio = 6, .active_low = 1, .default_trigger = "default-on" },
@ -199,7 +228,7 @@ arv4525pw_leds_gpio[] __initdata = {
};
static struct gpio_led
arv752dpw22_leds_gpio[] __initdata = {
arv752dpw22_gpio_leds[] __initdata = {
{ .name = "soc:blue:power", .gpio = 3, .active_low = 1, .default_trigger = "default-on" },
{ .name = "soc:red:internet", .gpio = 5, .active_low = 1, .default_trigger = "default-on" },
{ .name = "soc:red:power", .gpio = 6, .active_low = 1, .default_trigger = "default-on" },
@ -225,7 +254,7 @@ arv752dpw22_gpio_buttons[] __initdata = {
};
static struct gpio_led
arv7518pw_leds_gpio[] __initdata = {
arv7518pw_gpio_leds[] __initdata = {
{ .name = "soc:green:power", .gpio = 2, .active_low = 1, },
{ .name = "soc:green:adsl", .gpio = 4, .active_low = 1, },
{ .name = "soc:green:internet", .gpio = 5, .active_low = 1, },
@ -312,7 +341,7 @@ static void __init
arv3527p_init(void)
{
ltq_register_gpio_stp();
//ltq_add_device_leds_gpio(arv3527p_leds_gpio, ARRAY_SIZE(arv3527p_leds_gpio));
//ltq_add_device_gpio_leds(arv3527p_gpio_leds, ARRAY_SIZE(arv3527p_gpio_leds));
ltq_register_nor(&arv45xx_flash_data);
arv45xx_register_ethernet();
}
@ -326,7 +355,7 @@ static void __init
arv4510pw_init(void)
{
ltq_register_gpio_stp();
ltq_add_device_leds_gpio(-1, ARRAY_SIZE(arv4510pw_leds_gpio), arv4510pw_leds_gpio);
ltq_add_device_gpio_leds(-1, ARRAY_SIZE(arv4510pw_gpio_leds), arv4510pw_gpio_leds);
ltq_register_nor(&arv4510_flash_data);
ltq_pci_data.irq[12] = (INT_NUM_IM2_IRL0 + 31);
ltq_pci_data.irq[15] = (INT_NUM_IM0_IRL0 + 26);
@ -346,14 +375,15 @@ arv4518pw_init(void)
#define ARV4518PW_EBU 0
#define ARV4518PW_USB 14
#define ARV4518PW_SWITCH_RESET 13
#define ARV4518PW_MADWIFI_ADDR 0xb07f0400
ltq_register_gpio_ebu(ARV4518PW_EBU);
ltq_add_device_leds_gpio(-1, ARRAY_SIZE(arv4518pw_leds_gpio), arv4518pw_leds_gpio);
ltq_add_device_gpio_leds(-1, ARRAY_SIZE(arv4518pw_gpio_leds), arv4518pw_gpio_leds);
ltq_register_gpio_buttons(arv4518pw_gpio_buttons, ARRAY_SIZE(arv4518pw_gpio_buttons));
ltq_register_nor(&arv45xx_flash_data);
ltq_pci_data.gpio = PCI_GNT2 | PCI_REQ2;
ltq_register_pci(&ltq_pci_data);
ltq_register_madwifi_eep();
ltq_register_madwifi_eep(ARV4518PW_MADWIFI_ADDR);
xway_register_dwc(ARV4518PW_USB);
arv45xx_register_ethernet();
arv45xx_register_ath5k();
@ -376,7 +406,7 @@ arv4520pw_init(void)
#define ARV4520PW_SWITCH_RESET 110
ltq_register_gpio_ebu(ARV4520PW_EBU);
ltq_add_device_leds_gpio(-1, ARRAY_SIZE(arv4520pw_leds_gpio), arv4520pw_leds_gpio);
ltq_add_device_gpio_leds(-1, ARRAY_SIZE(arv4520pw_gpio_leds), arv4520pw_gpio_leds);
ltq_register_nor(&arv45xx_flash_data);
ltq_register_pci(&ltq_pci_data);
ltq_register_tapi();
@ -400,12 +430,13 @@ arv452Cpw_init(void)
#define ARV452CPW_RELAY1 31
#define ARV452CPW_RELAY2 107
#define ARV452CPW_SWITCH_RESET 110
#define ARV452CPW_MADWIFI_ADDR 0xb07f0400
ltq_register_gpio_ebu(ARV452CPW_EBU);
ltq_add_device_leds_gpio(-1, ARRAY_SIZE(arv452cpw_leds_gpio), arv452cpw_leds_gpio);
ltq_add_device_gpio_leds(-1, ARRAY_SIZE(arv452cpw_gpio_leds), arv452cpw_gpio_leds);
ltq_register_nor(&arv45xx_flash_data);
ltq_register_pci(&ltq_pci_data);
ltq_register_madwifi_eep();
ltq_register_madwifi_eep(ARV452CPW_MADWIFI_ADDR);
xway_register_dwc(ARV452CPW_USB);
arv45xx_register_ethernet();
arv45xx_register_ath5k();
@ -428,14 +459,16 @@ MIPS_MACHINE(LANTIQ_MACH_ARV452CPW,
"ARV452CPW - Arcor A801",
arv452Cpw_init);
#define ARV4525PW_MADWIFI_ADDR 0xb07f0400
static void __init
arv4525pw_init(void)
{
ltq_add_device_leds_gpio(-1, ARRAY_SIZE(arv4525pw_leds_gpio), arv4525pw_leds_gpio);
ltq_add_device_gpio_leds(-1, ARRAY_SIZE(arv4525pw_gpio_leds), arv4525pw_gpio_leds);
ltq_register_nor(&arv45xx_flash_data);
ltq_pci_data.clock = PCI_CLOCK_INT;
ltq_register_pci(&ltq_pci_data);
ltq_register_madwifi_eep();
ltq_register_madwifi_eep(ARV4525PW_MADWIFI_ADDR);
ltq_eth_data.mii_mode = PHY_INTERFACE_MODE_MII;
arv45xx_register_ethernet();
}
@ -445,6 +478,22 @@ MIPS_MACHINE(LANTIQ_MACH_ARV4525PW,
"ARV4525PW - Speedport W502V",
arv4525pw_init);
static void __init
arv7525pw_init(void)
{
ltq_add_device_gpio_leds(-1, ARRAY_SIZE(arv4525pw_gpio_leds), arv4525pw_gpio_leds);
ltq_register_nor(&arv7525_flash_data);
ltq_pci_data.clock = PCI_CLOCK_INT;
ltq_register_pci(&ltq_pci_data);
ltq_eth_data.mii_mode = PHY_INTERFACE_MODE_MII;
arv45xx_register_ethernet();
}
MIPS_MACHINE(LANTIQ_MACH_ARV7525PW,
"ARV7525PW",
"ARV7525PW - Speedport W303V",
arv7525pw_init);
static void __init
arv7518pw_init(void)
{
@ -452,7 +501,7 @@ arv7518pw_init(void)
#define ARV7518PW_USB 14
ltq_register_gpio_ebu(ARV7518PW_EBU);
ltq_add_device_leds_gpio(-1, ARRAY_SIZE(arv7518pw_leds_gpio), arv7518pw_leds_gpio);
ltq_add_device_gpio_leds(-1, ARRAY_SIZE(arv7518pw_gpio_leds), arv7518pw_gpio_leds);
ltq_register_gpio_buttons(arv7518pw_gpio_buttons, ARRAY_SIZE(arv7518pw_gpio_buttons));
ltq_register_nor(&arv75xx_flash_data);
ltq_register_pci(&ltq_pci_data);
@ -475,7 +524,7 @@ arv752dpw22_init(void)
#define ARV752DPW22_RELAY 101
ltq_register_gpio_ebu(ARV752DPW22_EBU);
ltq_add_device_leds_gpio(-1, ARRAY_SIZE(arv752dpw22_leds_gpio), arv752dpw22_leds_gpio);
ltq_add_device_gpio_leds(-1, ARRAY_SIZE(arv752dpw22_gpio_leds), arv752dpw22_gpio_leds);
ltq_register_gpio_buttons(arv752dpw22_gpio_buttons, ARRAY_SIZE(arv752dpw22_gpio_buttons));
ltq_register_nor(&arv75xx_flash_data);
ltq_pci_data.irq[15] = (INT_NUM_IM3_IRL0 + 31);

View File

@ -0,0 +1,212 @@
/*
* 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.
*
* Copyright (C) 2011 Andrej Vlašić
* Copyright (C) 2011 Luka Perkov
*
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/leds.h>
#include <linux/gpio.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
#include <linux/input.h>
#include <linux/ath5k_platform.h>
#include <linux/pci.h>
#include <linux/phy.h>
#include <linux/io.h>
#include <linux/string.h>
#include <irq.h>
#include <lantiq_soc.h>
#include <lantiq_platform.h>
#include <dev-gpio-leds.h>
#include <dev-gpio-buttons.h>
#include "../machtypes.h"
#include "devices.h"
#include "dev-dwc_otg.h"
#define UBOOT_ENV_OFFSET 0x010000
#define UBOOT_ENV_SIZE 0x010000
static struct mtd_partition gigasx76x_partitions[] =
{
{
.name = "uboot",
.offset = 0x000000,
.size = 0x010000,
},
{
.name = "uboot_env",
.offset = UBOOT_ENV_OFFSET,
.size = UBOOT_ENV_SIZE,
},
{
.name = "linux",
.offset = 0x020000,
.size = 0x7d0000,
},
{
.name = "board_config",
.offset = 0x7f0000,
.size = 0x010000,
},
};
static struct gpio_led
gigasx76x_gpio_leds[] __initdata = {
{ .name = "soc:green:usb", .gpio = 202, },
{ .name = "soc:green:wlan", .gpio = 203, },
{ .name = "soc:green:phone2", .gpio = 204, },
{ .name = "soc:green:phone1", .gpio = 205, },
{ .name = "soc:green:line", .gpio = 206, },
{ .name = "soc:green:online", .gpio = 207, },
{ .name = "soc:green:voip", .gpio = 208, },
};
static struct gpio_keys_button
gigasx76x_gpio_keys[] __initdata = {
{
.desc = "restart",
.type = EV_KEY,
.code = KEY_RESTART,
.debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
.gpio = 14,
.active_low = 1,
},
{
.desc = "wps",
.type = EV_KEY,
.code = KEY_WPS_BUTTON,
.debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
.gpio = 22,
.active_low = 1,
},
};
static struct physmap_flash_data gigasx76x_flash_data = {
.nr_parts = ARRAY_SIZE(gigasx76x_partitions),
.parts = gigasx76x_partitions,
};
static struct ltq_pci_data ltq_pci_data = {
.clock = PCI_CLOCK_INT,
.gpio = PCI_GNT1 | PCI_REQ1,
.irq = { [14] = INT_NUM_IM0_IRL0 + 22, },
};
static struct ltq_eth_data ltq_eth_data = {
.mii_mode = PHY_INTERFACE_MODE_MII,
};
static char __init *get_uboot_env_var(char *haystack, int haystack_len, char *needle, int needle_len) {
int i;
for (i = 0; i <= haystack_len - needle_len; i++) {
if (memcmp(haystack + i, needle, needle_len) == 0) {
return haystack + i + needle_len;
}
}
return NULL;
}
/*
* gigasx76x_parse_hex_* are not uniq. in arm/orion there are also duplicates:
* dns323_parse_hex_*
* TODO: one day write a patch for this :)
*/
static int __init gigasx76x_parse_hex_nibble(char n) {
if (n >= '0' && n <= '9')
return n - '0';
if (n >= 'A' && n <= 'F')
return n - 'A' + 10;
if (n >= 'a' && n <= 'f')
return n - 'a' + 10;
return -1;
}
static int __init gigasx76x_parse_hex_byte(const char *b) {
int hi;
int lo;
hi = gigasx76x_parse_hex_nibble(b[0]);
lo = gigasx76x_parse_hex_nibble(b[1]);
if (hi < 0 || lo < 0)
return -1;
return (hi << 4) | lo;
}
static int __init gigasx76x_register_ethernet(void) {
u_int8_t addr[6];
int i;
char *uboot_env_page;
char *mac;
uboot_env_page = ioremap(LTQ_FLASH_START + UBOOT_ENV_OFFSET, UBOOT_ENV_SIZE);
if (!uboot_env_page)
return -ENOMEM;
mac = get_uboot_env_var(uboot_env_page, UBOOT_ENV_SIZE, "\0ethaddr=", 9);
if (!mac) {
goto error_fail;
}
/* Sanity check the string we're looking at */
for (i = 0; i < 5; i++) {
if (*(mac + (i * 3) + 2) != ':') {
goto error_fail;
}
}
for (i = 0; i < 6; i++) {
int byte;
byte = gigasx76x_parse_hex_byte(mac + (i * 3));
if (byte < 0) {
goto error_fail;
}
addr[i] = byte;
}
iounmap(uboot_env_page);
printk("GIGASX76X: Found ethernet MAC address: ");
for (i = 0; i < 6; i++)
printk("%.2x%s", addr[i], (i < 5) ? ":" : ".\n");
memcpy(&ltq_eth_data.mac.sa_data, addr, 6);
ltq_register_etop(&ltq_eth_data);
return 0;
error_fail:
iounmap(uboot_env_page);
return -EINVAL;
}
static void __init gigasx76x_init(void) {
#define GIGASX76X_USB 29
#define GIGASX76X_MADWIFI_ADDR 0xb07f0000
ltq_register_gpio_stp();
ltq_register_nor(&gigasx76x_flash_data);
ltq_register_pci(&ltq_pci_data);
gigasx76x_register_ethernet();
xway_register_dwc(GIGASX76X_USB);
ltq_register_tapi();
ltq_register_madwifi_eep(GIGASX76X_MADWIFI_ADDR);
ltq_add_device_gpio_leds(-1, ARRAY_SIZE(gigasx76x_gpio_leds), gigasx76x_gpio_leds);
ltq_register_gpio_keys_polled(-1, LTQ_KEYS_POLL_INTERVAL, ARRAY_SIZE(gigasx76x_gpio_keys), gigasx76x_gpio_keys);
}
MIPS_MACHINE(LANTIQ_MACH_GIGASX76X, "GIGASX76X", "GIGASX76X - Gigaset SX761,SX762,SX763", gigasx76x_init);

View File

@ -18,10 +18,10 @@
#include <lantiq_soc.h>
#include <irq.h>
#include <dev-gpio-leds.h>
#include <dev-gpio-buttons.h>
#include "../machtypes.h"
#include "../dev-leds-gpio.h"
#include "../dev-gpio-buttons.h"
#include "devices.h"
#include "dev-dwc_otg.h"
@ -55,7 +55,7 @@ static struct physmap_flash_data wbmr_flash_data = {
};
static struct gpio_led
wbmr_leds_gpio[] __initdata = {
wbmr_gpio_leds[] __initdata = {
{ .name = "soc:blue:movie", .gpio = 20, .active_low = 1, },
{ .name = "soc:red:internet", .gpio = 18, .active_low = 1, },
{ .name = "soc:green:internet", .gpio = 17, .active_low = 1, },
@ -104,7 +104,7 @@ wbmr_init(void)
{
#define WMBR_BRN_MAC 0x1fd0024
ltq_add_device_leds_gpio(-1, ARRAY_SIZE(wbmr_leds_gpio), wbmr_leds_gpio);
ltq_add_device_gpio_leds(-1, ARRAY_SIZE(wbmr_gpio_leds), wbmr_gpio_leds);
ltq_register_gpio_keys_polled(-1, LTQ_KEYS_POLL_INTERVAL, ARRAY_SIZE(wbmr_gpio_keys), wbmr_gpio_keys);
ltq_register_nor(&wbmr_flash_data);
ltq_register_pci(&ltq_pci_data);

View File

@ -1,894 +0,0 @@
From 9e0235e97ea2617beaacaa16ab5f0b9e75f4680e Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Wed, 30 Mar 2011 09:27:47 +0200
Subject: [PATCH 01/13] MIPS: Lantiq: Add initial support for Lantiq SoCs
Add initial support for Mips based SoCs made by Lantiq. This series will add
support for the XWAY family.
The series allows booting a minimal system using a initramfs or NOR. Missing
drivers and support for Amazon and GPON family will be provided in a later
series.
[Ralf: Remove some cargo cult programming and fixed formatting.]
Signed-off-by: John Crispin <blogic@openwrt.org>
Signed-off-by: Ralph Hempel <ralph.hempel@lantiq.com>
Signed-off-by: David Daney <ddaney@caviumnetworks.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/2252/
Patchwork: https://patchwork.linux-mips.org/patch/2371/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
arch/mips/Kbuild.platforms | 1 +
arch/mips/Kconfig | 17 ++
arch/mips/include/asm/mach-lantiq/lantiq.h | 63 ++++++
arch/mips/include/asm/mach-lantiq/war.h | 24 ++
arch/mips/lantiq/Makefile | 9 +
arch/mips/lantiq/Platform | 7 +
arch/mips/lantiq/clk.c | 140 ++++++++++++
arch/mips/lantiq/clk.h | 18 ++
arch/mips/lantiq/early_printk.c | 33 +++
arch/mips/lantiq/irq.c | 326 ++++++++++++++++++++++++++++
arch/mips/lantiq/prom.c | 71 ++++++
arch/mips/lantiq/prom.h | 24 ++
arch/mips/lantiq/setup.c | 41 ++++
13 files changed, 774 insertions(+), 0 deletions(-)
create mode 100644 arch/mips/include/asm/mach-lantiq/lantiq.h
create mode 100644 arch/mips/include/asm/mach-lantiq/war.h
create mode 100644 arch/mips/lantiq/Makefile
create mode 100644 arch/mips/lantiq/Platform
create mode 100644 arch/mips/lantiq/clk.c
create mode 100644 arch/mips/lantiq/clk.h
create mode 100644 arch/mips/lantiq/early_printk.c
create mode 100644 arch/mips/lantiq/irq.c
create mode 100644 arch/mips/lantiq/prom.c
create mode 100644 arch/mips/lantiq/prom.h
create mode 100644 arch/mips/lantiq/setup.c
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -212,6 +212,23 @@ config MACH_JZ4740
select HAVE_PWM
select HAVE_CLK
+config LANTIQ
+ bool "Lantiq based platforms"
+ select DMA_NONCOHERENT
+ select IRQ_CPU
+ select CEVT_R4K
+ select CSRC_R4K
+ select SYS_HAS_CPU_MIPS32_R1
+ select SYS_HAS_CPU_MIPS32_R2
+ select SYS_SUPPORTS_BIG_ENDIAN
+ select SYS_SUPPORTS_32BIT_KERNEL
+ select SYS_SUPPORTS_MULTITHREADING
+ select SYS_HAS_EARLY_PRINTK
+ select ARCH_REQUIRE_GPIOLIB
+ select SWAP_IO_SPACE
+ select BOOT_RAW
+ select HAVE_CLK
+
config LASAT
bool "LASAT Networks platforms"
select CEVT_R4K
--- /dev/null
+++ b/arch/mips/include/asm/mach-lantiq/lantiq.h
@@ -0,0 +1,63 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+#ifndef _LANTIQ_H__
+#define _LANTIQ_H__
+
+#include <linux/irq.h>
+
+/* generic reg access functions */
+#define ltq_r32(reg) __raw_readl(reg)
+#define ltq_w32(val, reg) __raw_writel(val, reg)
+#define ltq_w32_mask(clear, set, reg) \
+ ltq_w32((ltq_r32(reg) & ~(clear)) | (set), reg)
+#define ltq_r8(reg) __raw_readb(reg)
+#define ltq_w8(val, reg) __raw_writeb(val, reg)
+
+/* register access macros for EBU and CGU */
+#define ltq_ebu_w32(x, y) ltq_w32((x), ltq_ebu_membase + (y))
+#define ltq_ebu_r32(x) ltq_r32(ltq_ebu_membase + (x))
+#define ltq_cgu_w32(x, y) ltq_w32((x), ltq_cgu_membase + (y))
+#define ltq_cgu_r32(x) ltq_r32(ltq_cgu_membase + (x))
+
+extern __iomem void *ltq_ebu_membase;
+extern __iomem void *ltq_cgu_membase;
+
+extern unsigned int ltq_get_cpu_ver(void);
+extern unsigned int ltq_get_soc_type(void);
+
+/* clock speeds */
+#define CLOCK_60M 60000000
+#define CLOCK_83M 83333333
+#define CLOCK_111M 111111111
+#define CLOCK_133M 133333333
+#define CLOCK_167M 166666667
+#define CLOCK_200M 200000000
+#define CLOCK_266M 266666666
+#define CLOCK_333M 333333333
+#define CLOCK_400M 400000000
+
+/* spinlock all ebu i/o */
+extern spinlock_t ebu_lock;
+
+/* some irq helpers */
+extern void ltq_disable_irq(struct irq_data *d);
+extern void ltq_mask_and_ack_irq(struct irq_data *d);
+extern void ltq_enable_irq(struct irq_data *d);
+
+/* find out what caused the last cpu reset */
+extern int ltq_reset_cause(void);
+#define LTQ_RST_CAUSE_WDTRST 0x20
+
+#define IOPORT_RESOURCE_START 0x10000000
+#define IOPORT_RESOURCE_END 0xffffffff
+#define IOMEM_RESOURCE_START 0x10000000
+#define IOMEM_RESOURCE_END 0xffffffff
+#define LTQ_FLASH_START 0x10000000
+#define LTQ_FLASH_MAX 0x04000000
+
+#endif
--- /dev/null
+++ b/arch/mips/include/asm/mach-lantiq/war.h
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ *
+ */
+#ifndef __ASM_MIPS_MACH_LANTIQ_WAR_H
+#define __ASM_MIPS_MACH_LANTIQ_WAR_H
+
+#define R4600_V1_INDEX_ICACHEOP_WAR 0
+#define R4600_V1_HIT_CACHEOP_WAR 0
+#define R4600_V2_HIT_CACHEOP_WAR 0
+#define R5432_CP0_INTERRUPT_WAR 0
+#define BCM1250_M3_WAR 0
+#define SIBYTE_1956_WAR 0
+#define MIPS4K_ICACHE_REFILL_WAR 0
+#define MIPS_CACHE_SYNC_WAR 0
+#define TX49XX_ICACHE_INDEX_INV_WAR 0
+#define RM9000_CDEX_SMP_WAR 0
+#define ICACHE_REFILLS_WORKAROUND_WAR 0
+#define R10000_LLSC_WAR 0
+#define MIPS34K_MISSED_ITLB_WAR 0
+
+#endif
--- /dev/null
+++ b/arch/mips/lantiq/Makefile
@@ -0,0 +1,9 @@
+# Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+#
+# 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.
+
+obj-y := irq.o setup.o clk.o prom.o
+
+obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
--- /dev/null
+++ b/arch/mips/lantiq/Platform
@@ -0,0 +1,7 @@
+#
+# Lantiq
+#
+
+platform-$(CONFIG_LANTIQ) += lantiq/
+cflags-$(CONFIG_LANTIQ) += -I$(srctree)/arch/mips/include/asm/mach-lantiq
+load-$(CONFIG_LANTIQ) = 0xffffffff80002000
--- /dev/null
+++ b/arch/mips/lantiq/clk.c
@@ -0,0 +1,144 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2010 Thomas Langer <thomas.langer@lantiq.com>
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/list.h>
+
+#include <asm/time.h>
+#include <asm/irq.h>
+#include <asm/div64.h>
+
+#include <lantiq_soc.h>
+
+#include "clk.h"
+
+struct clk {
+ const char *name;
+ unsigned long rate;
+ unsigned long (*get_rate) (void);
+};
+
+static struct clk *cpu_clk;
+static int cpu_clk_cnt;
+
+/* lantiq socs have 3 static clocks */
+static struct clk cpu_clk_generic[] = {
+ {
+ .name = "cpu",
+ .get_rate = ltq_get_cpu_hz,
+ }, {
+ .name = "fpi",
+ .get_rate = ltq_get_fpi_hz,
+ }, {
+ .name = "io",
+ .get_rate = ltq_get_io_region_clock,
+ },
+};
+
+#ifdef CONFIG_SOC_TYPE_XWAY
+static struct resource ltq_cgu_resource = {
+ .name = "cgu",
+ .start = LTQ_CGU_BASE_ADDR,
+ .end = LTQ_CGU_BASE_ADDR + LTQ_CGU_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+/* remapped clock register range */
+void __iomem *ltq_cgu_membase;
+#endif
+
+void clk_init(void)
+{
+ cpu_clk = cpu_clk_generic;
+ cpu_clk_cnt = ARRAY_SIZE(cpu_clk_generic);
+}
+
+static inline int clk_good(struct clk *clk)
+{
+ return clk && !IS_ERR(clk);
+}
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+ if (unlikely(!clk_good(clk)))
+ return 0;
+
+ if (clk->rate != 0)
+ return clk->rate;
+
+ if (clk->get_rate != NULL)
+ return clk->get_rate();
+
+ return 0;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+ int i;
+
+ for (i = 0; i < cpu_clk_cnt; i++)
+ if (!strcmp(id, cpu_clk[i].name))
+ return &cpu_clk[i];
+ BUG();
+ return ERR_PTR(-ENOENT);
+}
+EXPORT_SYMBOL(clk_get);
+
+void clk_put(struct clk *clk)
+{
+ /* not used */
+}
+EXPORT_SYMBOL(clk_put);
+
+static inline u32 ltq_get_counter_resolution(void)
+{
+ u32 res;
+
+ __asm__ __volatile__(
+ ".set push\n"
+ ".set mips32r2\n"
+ "rdhwr %0, $3\n"
+ ".set pop\n"
+ : "=&r" (res)
+ : /* no input */
+ : "memory");
+
+ return res;
+}
+
+void __init plat_time_init(void)
+{
+ struct clk *clk;
+
+#ifdef CONFIG_SOC_TYPE_XWAY
+ if (insert_resource(&iomem_resource, &ltq_cgu_resource) < 0)
+ panic("Failed to insert cgu memory\n");
+
+ if (request_mem_region(ltq_cgu_resource.start,
+ resource_size(&ltq_cgu_resource), "cgu") < 0)
+ panic("Failed to request cgu memory\n");
+
+ ltq_cgu_membase = ioremap_nocache(ltq_cgu_resource.start,
+ resource_size(&ltq_cgu_resource));
+ if (!ltq_cgu_membase) {
+ pr_err("Failed to remap cgu memory\n");
+ unreachable();
+ }
+#endif
+ clk = clk_get(0, "cpu");
+ mips_hpt_frequency = clk_get_rate(clk) / ltq_get_counter_resolution();
+ write_c0_compare(read_c0_count());
+ clk_put(clk);
+}
--- /dev/null
+++ b/arch/mips/lantiq/clk.h
@@ -0,0 +1,18 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#ifndef _LTQ_CLK_H__
+#define _LTQ_CLK_H__
+
+extern void clk_init(void);
+
+extern unsigned long ltq_get_cpu_hz(void);
+extern unsigned long ltq_get_fpi_hz(void);
+extern unsigned long ltq_get_io_region_clock(void);
+
+#endif
--- /dev/null
+++ b/arch/mips/lantiq/early_printk.c
@@ -0,0 +1,37 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/cpu.h>
+
+#include <lantiq.h>
+#include <lantiq_soc.h>
+
+/* no ioremap possible at this early stage, lets use KSEG1 instead */
+#ifdef CONFIG_SOC_FALCON
+#define LTQ_ASC_BASE KSEG1ADDR(LTQ_ASC0_BASE_ADDR)
+#else
+#define LTQ_ASC_BASE KSEG1ADDR(LTQ_ASC1_BASE_ADDR)
+#endif
+#define ASC_BUF 1024
+#define LTQ_ASC_FSTAT ((u32 *)(LTQ_ASC_BASE + 0x0048))
+#define LTQ_ASC_TBUF ((u32 *)(LTQ_ASC_BASE + 0x0020))
+#define TXMASK 0x3F00
+#define TXOFFSET 8
+
+void prom_putchar(char c)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ do { } while ((ltq_r32(LTQ_ASC_FSTAT) & TXMASK) >> TXOFFSET);
+ if (c == '\n')
+ ltq_w32('\r', LTQ_ASC_TBUF);
+ ltq_w32(c, LTQ_ASC_TBUF);
+ local_irq_restore(flags);
+}
--- /dev/null
+++ b/arch/mips/lantiq/irq.c
@@ -0,0 +1,339 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2010 Thomas Langer <thomas.langer@lantiq.com>
+ */
+
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+
+#include <asm/bootinfo.h>
+#include <asm/irq_cpu.h>
+
+#include <lantiq_soc.h>
+#include <irq.h>
+
+/* register definitions */
+#define LTQ_ICU_IM0_ISR 0x0000
+#define LTQ_ICU_IM0_IER 0x0008
+#define LTQ_ICU_IM0_IOSR 0x0010
+#define LTQ_ICU_IM0_IRSR 0x0018
+#define LTQ_ICU_IM0_IMR 0x0020
+#define LTQ_ICU_IM1_ISR 0x0028
+#define LTQ_ICU_OFFSET (LTQ_ICU_IM1_ISR - LTQ_ICU_IM0_ISR)
+
+#ifdef CONFIG_SOC_TYPE_XWAY
+
+#define LTQ_EIU_EXIN_C 0x0000
+#define LTQ_EIU_EXIN_INIC 0x0004
+#define LTQ_EIU_EXIN_INEN 0x000C
+
+/* irq numbers used by the external interrupt unit (EIU) */
+#define LTQ_EIU_IR0 (INT_NUM_IM4_IRL0 + 30)
+#define LTQ_EIU_IR1 (INT_NUM_IM3_IRL0 + 31)
+#define LTQ_EIU_IR2 (INT_NUM_IM1_IRL0 + 26)
+#define LTQ_EIU_IR3 INT_NUM_IM1_IRL0
+#define LTQ_EIU_IR4 (INT_NUM_IM1_IRL0 + 1)
+#define LTQ_EIU_IR5 (INT_NUM_IM1_IRL0 + 2)
+#define LTQ_EIU_IR6 (INT_NUM_IM2_IRL0 + 30)
+
+#define MAX_EIU 6
+
+/* irqs generated by device attached to the EBU need to be acked in
+ * a special manner
+ */
+#define LTQ_ICU_EBU_IRQ 22
+
+#define ltq_eiu_w32(x, y) ltq_w32((x), ltq_eiu_membase + (y))
+#define ltq_eiu_r32(x) ltq_r32(ltq_eiu_membase + (x))
+
+static unsigned short ltq_eiu_irq[MAX_EIU] = {
+ LTQ_EIU_IR0,
+ LTQ_EIU_IR1,
+ LTQ_EIU_IR2,
+ LTQ_EIU_IR3,
+ LTQ_EIU_IR4,
+ LTQ_EIU_IR5,
+};
+
+static void __iomem *ltq_eiu_membase;
+
+static struct resource ltq_eiu_resource = {
+ .name = "eiu",
+ .start = LTQ_EIU_BASE_ADDR,
+ .end = LTQ_EIU_BASE_ADDR + LTQ_ICU_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+#endif
+
+static struct resource ltq_icu_resource = {
+ .name = "icu",
+ .start = LTQ_ICU_BASE_ADDR,
+ .end = LTQ_ICU_BASE_ADDR + LTQ_ICU_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+#define ltq_icu_w32(x, y) ltq_w32((x), ltq_icu_membase + (y))
+#define ltq_icu_r32(x) ltq_r32(ltq_icu_membase + (x))
+
+static void __iomem *ltq_icu_membase;
+
+
+void ltq_disable_irq(struct irq_data *d)
+{
+ u32 ier = LTQ_ICU_IM0_IER;
+ int irq_nr = d->irq - INT_NUM_IRQ0;
+
+ ier += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET);
+ irq_nr %= INT_NUM_IM_OFFSET;
+ ltq_icu_w32(ltq_icu_r32(ier) & ~(1 << irq_nr), ier);
+}
+
+void ltq_mask_and_ack_irq(struct irq_data *d)
+{
+ u32 ier = LTQ_ICU_IM0_IER;
+ u32 isr = LTQ_ICU_IM0_ISR;
+ int irq_nr = d->irq - INT_NUM_IRQ0;
+
+ ier += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET);
+ isr += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET);
+ irq_nr %= INT_NUM_IM_OFFSET;
+ ltq_icu_w32(ltq_icu_r32(ier) & ~(1 << irq_nr), ier);
+ ltq_icu_w32((1 << irq_nr), isr);
+}
+EXPORT_SYMBOL(ltq_mask_and_ack_irq);
+
+static void ltq_ack_irq(struct irq_data *d)
+{
+ u32 isr = LTQ_ICU_IM0_ISR;
+ int irq_nr = d->irq - INT_NUM_IRQ0;
+
+ isr += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET);
+ irq_nr %= INT_NUM_IM_OFFSET;
+ ltq_icu_w32((1 << irq_nr), isr);
+}
+
+void ltq_enable_irq(struct irq_data *d)
+{
+ u32 ier = LTQ_ICU_IM0_IER;
+ int irq_nr = d->irq - INT_NUM_IRQ0;
+
+ ier += LTQ_ICU_OFFSET * (irq_nr / INT_NUM_IM_OFFSET);
+ irq_nr %= INT_NUM_IM_OFFSET;
+ ltq_icu_w32(ltq_icu_r32(ier) | (1 << irq_nr), ier);
+}
+
+#ifdef CONFIG_SOC_TYPE_XWAY
+static unsigned int ltq_startup_eiu_irq(struct irq_data *d)
+{
+ int i;
+ int irq_nr = d->irq - INT_NUM_IRQ0;
+
+ ltq_enable_irq(d);
+ for (i = 0; i < MAX_EIU; i++) {
+ if (irq_nr == ltq_eiu_irq[i]) {
+ /* low level - we should really handle set_type */
+ ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_C) |
+ (0x6 << (i * 4)), LTQ_EIU_EXIN_C);
+ /* clear all pending */
+ ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INIC) & ~(1 << i),
+ LTQ_EIU_EXIN_INIC);
+ /* enable */
+ ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INEN) | (1 << i),
+ LTQ_EIU_EXIN_INEN);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static void ltq_shutdown_eiu_irq(struct irq_data *d)
+{
+ int i;
+ int irq_nr = d->irq - INT_NUM_IRQ0;
+
+ ltq_disable_irq(d);
+ for (i = 0; i < MAX_EIU; i++) {
+ if (irq_nr == ltq_eiu_irq[i]) {
+ /* disable */
+ ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INEN) & ~(1 << i),
+ LTQ_EIU_EXIN_INEN);
+ break;
+ }
+ }
+}
+#endif
+
+static struct irq_chip ltq_irq_type = {
+ "icu",
+ .irq_enable = ltq_enable_irq,
+ .irq_disable = ltq_disable_irq,
+ .irq_unmask = ltq_enable_irq,
+ .irq_ack = ltq_ack_irq,
+ .irq_mask = ltq_disable_irq,
+ .irq_mask_ack = ltq_mask_and_ack_irq,
+};
+
+#ifdef CONFIG_SOC_TYPE_XWAY
+static struct irq_chip ltq_eiu_type = {
+ "eiu",
+ .irq_startup = ltq_startup_eiu_irq,
+ .irq_shutdown = ltq_shutdown_eiu_irq,
+ .irq_enable = ltq_enable_irq,
+ .irq_disable = ltq_disable_irq,
+ .irq_unmask = ltq_enable_irq,
+ .irq_ack = ltq_ack_irq,
+ .irq_mask = ltq_disable_irq,
+ .irq_mask_ack = ltq_mask_and_ack_irq,
+};
+#endif
+
+static void ltq_hw_irqdispatch(int module)
+{
+ u32 irq;
+
+ irq = ltq_icu_r32(LTQ_ICU_IM0_IOSR + (module * LTQ_ICU_OFFSET));
+ if (irq == 0)
+ return;
+
+ /* silicon bug causes only the msb set to 1 to be valid. all
+ * other bits might be bogus
+ */
+ irq = __fls(irq);
+ do_IRQ((int)irq + INT_NUM_IM0_IRL0 + (INT_NUM_IM_OFFSET * module));
+
+#ifdef CONFIG_SOC_TYPE_XWAY
+ /* if this is a EBU irq, we need to ack it or get a deadlock */
+ if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0))
+ ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_ISTAT) | 0x10,
+ LTQ_EBU_PCC_ISTAT);
+#endif
+}
+
+#define DEFINE_HWx_IRQDISPATCH(x) \
+ static void ltq_hw ## x ## _irqdispatch(void) \
+ { \
+ ltq_hw_irqdispatch(x); \
+ }
+DEFINE_HWx_IRQDISPATCH(0)
+DEFINE_HWx_IRQDISPATCH(1)
+DEFINE_HWx_IRQDISPATCH(2)
+DEFINE_HWx_IRQDISPATCH(3)
+DEFINE_HWx_IRQDISPATCH(4)
+
+static void ltq_hw5_irqdispatch(void)
+{
+ do_IRQ(MIPS_CPU_TIMER_IRQ);
+}
+
+asmlinkage void plat_irq_dispatch(void)
+{
+ unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
+ unsigned int i;
+
+ if (pending & CAUSEF_IP7) {
+ do_IRQ(MIPS_CPU_TIMER_IRQ);
+ goto out;
+ } else {
+ for (i = 0; i < 5; i++) {
+ if (pending & (CAUSEF_IP2 << i)) {
+ ltq_hw_irqdispatch(i);
+ goto out;
+ }
+ }
+ }
+ pr_alert("Spurious IRQ: CAUSE=0x%08x\n", read_c0_status());
+
+out:
+ return;
+}
+
+static struct irqaction cascade = {
+ .handler = no_action,
+ .flags = IRQF_DISABLED,
+ .name = "cascade",
+};
+
+void __init arch_init_irq(void)
+{
+ int i;
+
+ if (insert_resource(&iomem_resource, &ltq_icu_resource) < 0)
+ panic("Failed to insert icu memory\n");
+
+ if (request_mem_region(ltq_icu_resource.start,
+ resource_size(&ltq_icu_resource), "icu") < 0)
+ panic("Failed to request icu memory\n");
+
+ ltq_icu_membase = ioremap_nocache(ltq_icu_resource.start,
+ resource_size(&ltq_icu_resource));
+ if (!ltq_icu_membase)
+ panic("Failed to remap icu memory\n");
+
+#ifdef CONFIG_SOC_TYPE_XWAY
+ if (insert_resource(&iomem_resource, &ltq_eiu_resource) < 0)
+ panic("Failed to insert eiu memory\n");
+
+ if (request_mem_region(ltq_eiu_resource.start,
+ resource_size(&ltq_eiu_resource), "eiu") < 0)
+ panic("Failed to request eiu memory\n");
+
+ ltq_eiu_membase = ioremap_nocache(ltq_eiu_resource.start,
+ resource_size(&ltq_eiu_resource));
+ if (!ltq_eiu_membase)
+ panic("Failed to remap eiu memory\n");
+#endif
+ /* make sure all irqs are turned off by default */
+ for (i = 0; i < 5; i++)
+ ltq_icu_w32(0, LTQ_ICU_IM0_IER + (i * LTQ_ICU_OFFSET));
+
+ /* clear all possibly pending interrupts */
+ ltq_icu_w32(~0, LTQ_ICU_IM0_ISR + (i * LTQ_ICU_OFFSET));
+
+ mips_cpu_irq_init();
+
+ for (i = 2; i <= 6; i++)
+ setup_irq(i, &cascade);
+
+ if (cpu_has_vint) {
+ pr_info("Setting up vectored interrupts\n");
+ set_vi_handler(2, ltq_hw0_irqdispatch);
+ set_vi_handler(3, ltq_hw1_irqdispatch);
+ set_vi_handler(4, ltq_hw2_irqdispatch);
+ set_vi_handler(5, ltq_hw3_irqdispatch);
+ set_vi_handler(6, ltq_hw4_irqdispatch);
+ set_vi_handler(7, ltq_hw5_irqdispatch);
+ }
+
+ for (i = INT_NUM_IRQ0;
+ i <= (INT_NUM_IRQ0 + (5 * INT_NUM_IM_OFFSET)); i++)
+#ifdef CONFIG_SOC_TYPE_XWAY
+ if ((i == LTQ_EIU_IR0) || (i == LTQ_EIU_IR1) || (i == LTQ_EIU_IR2))
+ irq_set_chip_and_handler(i, &ltq_eiu_type, handle_level_irq);
+ /* EIU3-5 only exist on ar9 and vr9 */
+ else if (((i == LTQ_EIU_IR3) || (i == LTQ_EIU_IR4) ||
+ (i == LTQ_EIU_IR5)) && (ltq_is_ar9() || ltq_is_vr9()))
+ irq_set_chip_and_handler(i, &ltq_eiu_type, handle_level_irq);
+ else
+#endif
+ irq_set_chip_and_handler(i, &ltq_irq_type, handle_level_irq);
+
+#if !defined(CONFIG_MIPS_MT_SMP) && !defined(CONFIG_MIPS_MT_SMTC)
+ set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 |
+ IE_IRQ3 | IE_IRQ4 | IE_IRQ5);
+#else
+ set_c0_status(IE_SW0 | IE_SW1 | IE_IRQ0 | IE_IRQ1 |
+ IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5);
+#endif
+}
+
+unsigned int __cpuinit get_c0_compare_int(void)
+{
+ return CP0_LEGACY_COMPARE_IRQ;
+}
--- /dev/null
+++ b/arch/mips/lantiq/prom.c
@@ -0,0 +1,71 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <asm/bootinfo.h>
+#include <asm/time.h>
+
+#include <lantiq.h>
+
+#include "prom.h"
+#include "clk.h"
+
+static struct ltq_soc_info soc_info;
+
+unsigned int ltq_get_cpu_ver(void)
+{
+ return soc_info.rev;
+}
+EXPORT_SYMBOL(ltq_get_cpu_ver);
+
+unsigned int ltq_get_soc_type(void)
+{
+ return soc_info.type;
+}
+EXPORT_SYMBOL(ltq_get_soc_type);
+
+const char *get_system_type(void)
+{
+ return soc_info.sys_type;
+}
+
+void prom_free_prom_memory(void)
+{
+}
+
+static void __init prom_init_cmdline(void)
+{
+ int argc = fw_arg0;
+ char **argv = (char **) KSEG1ADDR(fw_arg1);
+ int i;
+
+ for (i = 0; i < argc; i++) {
+ char *p = (char *) KSEG1ADDR(argv[i]);
+
+ if (p && *p) {
+ strlcat(arcs_cmdline, p, sizeof(arcs_cmdline));
+ strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline));
+ }
+ }
+}
+
+void __init prom_init(void)
+{
+ struct clk *clk;
+
+ ltq_soc_detect(&soc_info);
+ clk_init();
+ clk = clk_get(0, "cpu");
+ snprintf(soc_info.sys_type, LTQ_SYS_TYPE_LEN - 1, "%s rev1.%d",
+ soc_info.name, soc_info.rev);
+ clk_put(clk);
+ soc_info.sys_type[LTQ_SYS_TYPE_LEN - 1] = '\0';
+ pr_info("SoC: %s\n", soc_info.sys_type);
+ prom_init_cmdline();
+}
--- /dev/null
+++ b/arch/mips/lantiq/prom.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 version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#ifndef _LTQ_PROM_H__
+#define _LTQ_PROM_H__
+
+#define LTQ_SYS_TYPE_LEN 0x100
+
+struct ltq_soc_info {
+ unsigned char *name;
+ unsigned int rev;
+ unsigned int partnum;
+ unsigned int type;
+ unsigned char sys_type[LTQ_SYS_TYPE_LEN];
+};
+
+extern void ltq_soc_detect(struct ltq_soc_info *i);
+
+#endif
--- /dev/null
+++ b/arch/mips/lantiq/setup.c
@@ -0,0 +1,41 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <asm/bootinfo.h>
+
+#include <lantiq_soc.h>
+
+void __init plat_mem_setup(void)
+{
+ /* assume 16M as default incase uboot fails to pass proper ramsize */
+ unsigned long memsize = 16;
+ char **envp = (char **) KSEG1ADDR(fw_arg2);
+
+ ioport_resource.start = IOPORT_RESOURCE_START;
+ ioport_resource.end = IOPORT_RESOURCE_END;
+ iomem_resource.start = IOMEM_RESOURCE_START;
+ iomem_resource.end = IOMEM_RESOURCE_END;
+
+ set_io_port_base((unsigned long) KSEG1);
+
+ while (*envp) {
+ char *e = (char *)KSEG1ADDR(*envp);
+ if (!strncmp(e, "memsize=", 8)) {
+ e += 8;
+ if (strict_strtoul(e, 0, &memsize))
+ pr_warn("bad memsize specified\n");
+ }
+ envp++;
+ }
+ memsize *= 1024 * 1024;
+ add_memory_region(0x00000000, memsize, BOOT_MEM_RAM);
+}
--- a/arch/mips/Kbuild.platforms
+++ b/arch/mips/Kbuild.platforms
@@ -11,6 +11,7 @@ platforms += dec
platforms += emma
platforms += jazz
platforms += jz4740
+platforms += lantiq
platforms += lasat
platforms += loongson
platforms += mipssim

View File

@ -1,529 +0,0 @@
From 08127ed36bad367903591bbf0f244179683ccb28 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Wed, 30 Mar 2011 09:27:49 +0200
Subject: [PATCH 03/13] MIPS: Lantiq: Add PCI controller support.
The Lantiq family of SoCs have a EBU (External Bus Unit). This patch adds
the driver that allows us to use the EBU as a PCI controller. In order for
PCI to work the EBU is set to endianess swap all the data. In addition we
need to make use of SWAP_IO_SPACE for device->host DMA to work.
The clock of the PCI works in several modes (internal/external). If this
is not configured correctly the SoC will hang.
Signed-off-by: John Crispin <blogic@openwrt.org>
Signed-off-by: Ralph Hempel <ralph.hempel@lantiq.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/2250/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
.../mips/include/asm/mach-lantiq/lantiq_platform.h | 46 +++
arch/mips/pci/Makefile | 1 +
arch/mips/pci/ops-lantiq.c | 116 ++++++++
arch/mips/pci/pci-lantiq.c | 297 ++++++++++++++++++++
arch/mips/pci/pci-lantiq.h | 18 ++
5 files changed, 478 insertions(+), 0 deletions(-)
create mode 100644 arch/mips/include/asm/mach-lantiq/lantiq_platform.h
create mode 100644 arch/mips/pci/ops-lantiq.c
create mode 100644 arch/mips/pci/pci-lantiq.c
create mode 100644 arch/mips/pci/pci-lantiq.h
--- /dev/null
+++ b/arch/mips/include/asm/mach-lantiq/lantiq_platform.h
@@ -0,0 +1,46 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#ifndef _LANTIQ_PLATFORM_H__
+#define _LANTIQ_PLATFORM_H__
+
+#include <linux/mtd/partitions.h>
+
+/* struct used to pass info to the pci core */
+enum {
+ PCI_CLOCK_INT = 0,
+ PCI_CLOCK_EXT
+};
+
+#define PCI_EXIN0 0x0001
+#define PCI_EXIN1 0x0002
+#define PCI_EXIN2 0x0004
+#define PCI_EXIN3 0x0008
+#define PCI_EXIN4 0x0010
+#define PCI_EXIN5 0x0020
+#define PCI_EXIN_MAX 6
+
+#define PCI_GNT1 0x0040
+#define PCI_GNT2 0x0080
+#define PCI_GNT3 0x0100
+#define PCI_GNT4 0x0200
+
+#define PCI_REQ1 0x0400
+#define PCI_REQ2 0x0800
+#define PCI_REQ3 0x1000
+#define PCI_REQ4 0x2000
+#define PCI_REQ_SHIFT 10
+#define PCI_REQ_MASK 0xf
+
+struct ltq_pci_data {
+ int clock;
+ int gpio;
+ int irq[16];
+};
+
+#endif
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -41,6 +41,7 @@ obj-$(CONFIG_SIBYTE_SB1250) += fixup-sb1
obj-$(CONFIG_SIBYTE_BCM112X) += fixup-sb1250.o pci-sb1250.o
obj-$(CONFIG_SIBYTE_BCM1x80) += pci-bcm1480.o pci-bcm1480ht.o
obj-$(CONFIG_SNI_RM) += fixup-sni.o ops-sni.o
+obj-$(CONFIG_SOC_XWAY) += pci-lantiq.o ops-lantiq.o
obj-$(CONFIG_TANBAC_TB0219) += fixup-tb0219.o
obj-$(CONFIG_TANBAC_TB0226) += fixup-tb0226.o
obj-$(CONFIG_TANBAC_TB0287) += fixup-tb0287.o
--- /dev/null
+++ b/arch/mips/pci/ops-lantiq.c
@@ -0,0 +1,116 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <asm/addrspace.h>
+#include <linux/vmalloc.h>
+
+#include <lantiq_soc.h>
+
+#include "pci-lantiq.h"
+
+#define LTQ_PCI_CFG_BUSNUM_SHF 16
+#define LTQ_PCI_CFG_DEVNUM_SHF 11
+#define LTQ_PCI_CFG_FUNNUM_SHF 8
+
+#define PCI_ACCESS_READ 0
+#define PCI_ACCESS_WRITE 1
+
+static int ltq_pci_config_access(unsigned char access_type, struct pci_bus *bus,
+ unsigned int devfn, unsigned int where, u32 *data)
+{
+ unsigned long cfg_base;
+ unsigned long flags;
+ u32 temp;
+
+ /* we support slot from 0 to 15 dev_fn & 0x68 (AD29) is the
+ SoC itself */
+ if ((bus->number != 0) || ((devfn & 0xf8) > 0x78)
+ || ((devfn & 0xf8) == 0) || ((devfn & 0xf8) == 0x68))
+ return 1;
+
+ spin_lock_irqsave(&ebu_lock, flags);
+
+ cfg_base = (unsigned long) ltq_pci_mapped_cfg;
+ cfg_base |= (bus->number << LTQ_PCI_CFG_BUSNUM_SHF) | (devfn <<
+ LTQ_PCI_CFG_FUNNUM_SHF) | (where & ~0x3);
+
+ /* Perform access */
+ if (access_type == PCI_ACCESS_WRITE) {
+ ltq_w32(swab32(*data), ((u32 *)cfg_base));
+ } else {
+ *data = ltq_r32(((u32 *)(cfg_base)));
+ *data = swab32(*data);
+ }
+ wmb();
+
+ /* clean possible Master abort */
+ cfg_base = (unsigned long) ltq_pci_mapped_cfg;
+ cfg_base |= (0x0 << LTQ_PCI_CFG_FUNNUM_SHF) + 4;
+ temp = ltq_r32(((u32 *)(cfg_base)));
+ temp = swab32(temp);
+ cfg_base = (unsigned long) ltq_pci_mapped_cfg;
+ cfg_base |= (0x68 << LTQ_PCI_CFG_FUNNUM_SHF) + 4;
+ ltq_w32(temp, ((u32 *)cfg_base));
+
+ spin_unlock_irqrestore(&ebu_lock, flags);
+
+ if (((*data) == 0xffffffff) && (access_type == PCI_ACCESS_READ))
+ return 1;
+
+ return 0;
+}
+
+int ltq_pci_read_config_dword(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 *val)
+{
+ u32 data = 0;
+
+ if (ltq_pci_config_access(PCI_ACCESS_READ, bus, devfn, where, &data))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ if (size == 1)
+ *val = (data >> ((where & 3) << 3)) & 0xff;
+ else if (size == 2)
+ *val = (data >> ((where & 3) << 3)) & 0xffff;
+ else
+ *val = data;
+
+ return PCIBIOS_SUCCESSFUL;
+}
+
+int ltq_pci_write_config_dword(struct pci_bus *bus, unsigned int devfn,
+ int where, int size, u32 val)
+{
+ u32 data = 0;
+
+ if (size == 4) {
+ data = val;
+ } else {
+ if (ltq_pci_config_access(PCI_ACCESS_READ, bus,
+ devfn, where, &data))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ if (size == 1)
+ data = (data & ~(0xff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+ else if (size == 2)
+ data = (data & ~(0xffff << ((where & 3) << 3))) |
+ (val << ((where & 3) << 3));
+ }
+
+ if (ltq_pci_config_access(PCI_ACCESS_WRITE, bus, devfn, where, &data))
+ return PCIBIOS_DEVICE_NOT_FOUND;
+
+ return PCIBIOS_SUCCESSFUL;
+}
--- /dev/null
+++ b/arch/mips/pci/pci-lantiq.c
@@ -0,0 +1,297 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/platform_device.h>
+
+#include <asm/pci.h>
+#include <asm/gpio.h>
+#include <asm/addrspace.h>
+
+#include <lantiq_soc.h>
+#include <lantiq_irq.h>
+#include <lantiq_platform.h>
+
+#include "pci-lantiq.h"
+
+#define LTQ_PCI_CFG_BASE 0x17000000
+#define LTQ_PCI_CFG_SIZE 0x00008000
+#define LTQ_PCI_MEM_BASE 0x18000000
+#define LTQ_PCI_MEM_SIZE 0x02000000
+#define LTQ_PCI_IO_BASE 0x1AE00000
+#define LTQ_PCI_IO_SIZE 0x00200000
+
+#define PCI_CR_FCI_ADDR_MAP0 0x00C0
+#define PCI_CR_FCI_ADDR_MAP1 0x00C4
+#define PCI_CR_FCI_ADDR_MAP2 0x00C8
+#define PCI_CR_FCI_ADDR_MAP3 0x00CC
+#define PCI_CR_FCI_ADDR_MAP4 0x00D0
+#define PCI_CR_FCI_ADDR_MAP5 0x00D4
+#define PCI_CR_FCI_ADDR_MAP6 0x00D8
+#define PCI_CR_FCI_ADDR_MAP7 0x00DC
+#define PCI_CR_CLK_CTRL 0x0000
+#define PCI_CR_PCI_MOD 0x0030
+#define PCI_CR_PC_ARB 0x0080
+#define PCI_CR_FCI_ADDR_MAP11hg 0x00E4
+#define PCI_CR_BAR11MASK 0x0044
+#define PCI_CR_BAR12MASK 0x0048
+#define PCI_CR_BAR13MASK 0x004C
+#define PCI_CS_BASE_ADDR1 0x0010
+#define PCI_CR_PCI_ADDR_MAP11 0x0064
+#define PCI_CR_FCI_BURST_LENGTH 0x00E8
+#define PCI_CR_PCI_EOI 0x002C
+#define PCI_CS_STS_CMD 0x0004
+
+#define PCI_MASTER0_REQ_MASK_2BITS 8
+#define PCI_MASTER1_REQ_MASK_2BITS 10
+#define PCI_MASTER2_REQ_MASK_2BITS 12
+#define INTERNAL_ARB_ENABLE_BIT 0
+
+#define LTQ_CGU_IFCCR 0x0018
+#define LTQ_CGU_PCICR 0x0034
+
+#define ltq_pci_w32(x, y) ltq_w32((x), ltq_pci_membase + (y))
+#define ltq_pci_r32(x) ltq_r32(ltq_pci_membase + (x))
+
+#define ltq_pci_cfg_w32(x, y) ltq_w32((x), ltq_pci_mapped_cfg + (y))
+#define ltq_pci_cfg_r32(x) ltq_r32(ltq_pci_mapped_cfg + (x))
+
+struct ltq_pci_gpio_map {
+ int pin;
+ int alt0;
+ int alt1;
+ int dir;
+ char *name;
+};
+
+/* the pci core can make use of the following gpios */
+static struct ltq_pci_gpio_map ltq_pci_gpio_map[] = {
+ { 0, 1, 0, 0, "pci-exin0" },
+ { 1, 1, 0, 0, "pci-exin1" },
+ { 2, 1, 0, 0, "pci-exin2" },
+ { 39, 1, 0, 0, "pci-exin3" },
+ { 10, 1, 0, 0, "pci-exin4" },
+ { 9, 1, 0, 0, "pci-exin5" },
+ { 30, 1, 0, 1, "pci-gnt1" },
+ { 23, 1, 0, 1, "pci-gnt2" },
+ { 19, 1, 0, 1, "pci-gnt3" },
+ { 38, 1, 0, 1, "pci-gnt4" },
+ { 29, 1, 0, 0, "pci-req1" },
+ { 31, 1, 0, 0, "pci-req2" },
+ { 3, 1, 0, 0, "pci-req3" },
+ { 37, 1, 0, 0, "pci-req4" },
+};
+
+__iomem void *ltq_pci_mapped_cfg;
+static __iomem void *ltq_pci_membase;
+
+int (*ltqpci_plat_dev_init)(struct pci_dev *dev) = NULL;
+
+/* Since the PCI REQ pins can be reused for other functionality, make it
+ possible to exclude those from interpretation by the PCI controller */
+static int ltq_pci_req_mask = 0xf;
+
+static int *ltq_pci_irq_map;
+
+struct pci_ops ltq_pci_ops = {
+ .read = ltq_pci_read_config_dword,
+ .write = ltq_pci_write_config_dword
+};
+
+static struct resource pci_io_resource = {
+ .name = "pci io space",
+ .start = LTQ_PCI_IO_BASE,
+ .end = LTQ_PCI_IO_BASE + LTQ_PCI_IO_SIZE - 1,
+ .flags = IORESOURCE_IO
+};
+
+static struct resource pci_mem_resource = {
+ .name = "pci memory space",
+ .start = LTQ_PCI_MEM_BASE,
+ .end = LTQ_PCI_MEM_BASE + LTQ_PCI_MEM_SIZE - 1,
+ .flags = IORESOURCE_MEM
+};
+
+static struct pci_controller ltq_pci_controller = {
+ .pci_ops = &ltq_pci_ops,
+ .mem_resource = &pci_mem_resource,
+ .mem_offset = 0x00000000UL,
+ .io_resource = &pci_io_resource,
+ .io_offset = 0x00000000UL,
+};
+
+int pcibios_plat_dev_init(struct pci_dev *dev)
+{
+ if (ltqpci_plat_dev_init)
+ return ltqpci_plat_dev_init(dev);
+
+ return 0;
+}
+
+static u32 ltq_calc_bar11mask(void)
+{
+ u32 mem, bar11mask;
+
+ /* BAR11MASK value depends on available memory on system. */
+ mem = num_physpages * PAGE_SIZE;
+ bar11mask = (0x0ffffff0 & ~((1 << (fls(mem) - 1)) - 1)) | 8;
+
+ return bar11mask;
+}
+
+static void ltq_pci_setup_gpio(int gpio)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(ltq_pci_gpio_map); i++) {
+ if (gpio & (1 << i)) {
+ ltq_gpio_request(ltq_pci_gpio_map[i].pin,
+ ltq_pci_gpio_map[i].alt0,
+ ltq_pci_gpio_map[i].alt1,
+ ltq_pci_gpio_map[i].dir,
+ ltq_pci_gpio_map[i].name);
+ }
+ }
+ ltq_gpio_request(21, 0, 0, 1, "pci-reset");
+ ltq_pci_req_mask = (gpio >> PCI_REQ_SHIFT) & PCI_REQ_MASK;
+}
+
+static int __devinit ltq_pci_startup(struct ltq_pci_data *conf)
+{
+ u32 temp_buffer;
+
+ /* set clock to 33Mhz */
+ ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~0xf00000, LTQ_CGU_IFCCR);
+ ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | 0x800000, LTQ_CGU_IFCCR);
+
+ /* external or internal clock ? */
+ if (conf->clock) {
+ ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~(1 << 16),
+ LTQ_CGU_IFCCR);
+ ltq_cgu_w32((1 << 30), LTQ_CGU_PCICR);
+ } else {
+ ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | (1 << 16),
+ LTQ_CGU_IFCCR);
+ ltq_cgu_w32((1 << 31) | (1 << 30), LTQ_CGU_PCICR);
+ }
+
+ /* setup pci clock and gpis used by pci */
+ ltq_pci_setup_gpio(conf->gpio);
+
+ /* enable auto-switching between PCI and EBU */
+ ltq_pci_w32(0xa, PCI_CR_CLK_CTRL);
+
+ /* busy, i.e. configuration is not done, PCI access has to be retried */
+ ltq_pci_w32(ltq_pci_r32(PCI_CR_PCI_MOD) & ~(1 << 24), PCI_CR_PCI_MOD);
+ wmb();
+ /* BUS Master/IO/MEM access */
+ ltq_pci_cfg_w32(ltq_pci_cfg_r32(PCI_CS_STS_CMD) | 7, PCI_CS_STS_CMD);
+
+ /* enable external 2 PCI masters */
+ temp_buffer = ltq_pci_r32(PCI_CR_PC_ARB);
+ temp_buffer &= (~(ltq_pci_req_mask << 16));
+ /* enable internal arbiter */
+ temp_buffer |= (1 << INTERNAL_ARB_ENABLE_BIT);
+ /* enable internal PCI master reqest */
+ temp_buffer &= (~(3 << PCI_MASTER0_REQ_MASK_2BITS));
+
+ /* enable EBU request */
+ temp_buffer &= (~(3 << PCI_MASTER1_REQ_MASK_2BITS));
+
+ /* enable all external masters request */
+ temp_buffer &= (~(3 << PCI_MASTER2_REQ_MASK_2BITS));
+ ltq_pci_w32(temp_buffer, PCI_CR_PC_ARB);
+ wmb();
+
+ /* setup BAR memory regions */
+ ltq_pci_w32(0x18000000, PCI_CR_FCI_ADDR_MAP0);
+ ltq_pci_w32(0x18400000, PCI_CR_FCI_ADDR_MAP1);
+ ltq_pci_w32(0x18800000, PCI_CR_FCI_ADDR_MAP2);
+ ltq_pci_w32(0x18c00000, PCI_CR_FCI_ADDR_MAP3);
+ ltq_pci_w32(0x19000000, PCI_CR_FCI_ADDR_MAP4);
+ ltq_pci_w32(0x19400000, PCI_CR_FCI_ADDR_MAP5);
+ ltq_pci_w32(0x19800000, PCI_CR_FCI_ADDR_MAP6);
+ ltq_pci_w32(0x19c00000, PCI_CR_FCI_ADDR_MAP7);
+ ltq_pci_w32(0x1ae00000, PCI_CR_FCI_ADDR_MAP11hg);
+ ltq_pci_w32(ltq_calc_bar11mask(), PCI_CR_BAR11MASK);
+ ltq_pci_w32(0, PCI_CR_PCI_ADDR_MAP11);
+ ltq_pci_w32(0, PCI_CS_BASE_ADDR1);
+ /* both TX and RX endian swap are enabled */
+ ltq_pci_w32(ltq_pci_r32(PCI_CR_PCI_EOI) | 3, PCI_CR_PCI_EOI);
+ wmb();
+ ltq_pci_w32(ltq_pci_r32(PCI_CR_BAR12MASK) | 0x80000000,
+ PCI_CR_BAR12MASK);
+ ltq_pci_w32(ltq_pci_r32(PCI_CR_BAR13MASK) | 0x80000000,
+ PCI_CR_BAR13MASK);
+ /*use 8 dw burst length */
+ ltq_pci_w32(0x303, PCI_CR_FCI_BURST_LENGTH);
+ ltq_pci_w32(ltq_pci_r32(PCI_CR_PCI_MOD) | (1 << 24), PCI_CR_PCI_MOD);
+ wmb();
+
+ /* setup irq line */
+ ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_CON) | 0xc, LTQ_EBU_PCC_CON);
+ ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_PCC_IEN) | 0x10, LTQ_EBU_PCC_IEN);
+
+ /* toggle reset pin */
+ __gpio_set_value(21, 0);
+ wmb();
+ mdelay(1);
+ __gpio_set_value(21, 1);
+ return 0;
+}
+
+int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+{
+ if (ltq_pci_irq_map[slot])
+ return ltq_pci_irq_map[slot];
+ printk(KERN_ERR "ltq_pci: trying to map irq for unknown slot %d\n",
+ slot);
+
+ return 0;
+}
+
+static int __devinit ltq_pci_probe(struct platform_device *pdev)
+{
+ struct ltq_pci_data *ltq_pci_data =
+ (struct ltq_pci_data *) pdev->dev.platform_data;
+ pci_probe_only = 0;
+ ltq_pci_irq_map = ltq_pci_data->irq;
+ ltq_pci_membase = ioremap_nocache(PCI_CR_BASE_ADDR, PCI_CR_SIZE);
+ ltq_pci_mapped_cfg =
+ ioremap_nocache(LTQ_PCI_CFG_BASE, LTQ_PCI_CFG_BASE);
+ ltq_pci_controller.io_map_base =
+ (unsigned long)ioremap(LTQ_PCI_IO_BASE, LTQ_PCI_IO_SIZE - 1);
+ ltq_pci_startup(ltq_pci_data);
+ register_pci_controller(&ltq_pci_controller);
+
+ return 0;
+}
+
+static struct platform_driver
+ltq_pci_driver = {
+ .probe = ltq_pci_probe,
+ .driver = {
+ .name = "ltq_pci",
+ .owner = THIS_MODULE,
+ },
+};
+
+int __init pcibios_init(void)
+{
+ int ret = platform_driver_register(&ltq_pci_driver);
+ if (ret)
+ printk(KERN_INFO "ltq_pci: Error registering platfom driver!");
+ return ret;
+}
+
+arch_initcall(pcibios_init);
--- /dev/null
+++ b/arch/mips/pci/pci-lantiq.h
@@ -0,0 +1,18 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#ifndef _LTQ_PCI_H__
+#define _LTQ_PCI_H__
+
+extern __iomem void *ltq_pci_mapped_cfg;
+extern int ltq_pci_read_config_dword(struct pci_bus *bus,
+ unsigned int devfn, int where, int size, u32 *val);
+extern int ltq_pci_write_config_dword(struct pci_bus *bus,
+ unsigned int devfn, int where, int size, u32 val);
+
+#endif

View File

@ -1,301 +0,0 @@
From cd0d53b24ca744295d2cdf69bb2b659571091b75 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Tue, 12 Apr 2011 18:10:01 +0200
Subject: [PATCH 04/13] MIPS: Lantiq: Add NOR flash support
This patch adds the driver/map for NOR devices attached to the SoC via the
External Bus Unit (EBU).
Signed-off-by: John Crispin <blogic@openwrt.org>
Signed-off-by: Ralph Hempel <ralph.hempel@lantiq.com>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Daniel Schwierzeck <daniel.schwierzeck@googlemail.com>
Cc: linux-mips@linux-mips.org
Cc: linux-mtd@lists.infradead.org
Acked-by: Artem Bityutskiy <dedekind1@gmail.com>
Patchwork: https://patchwork.linux-mips.org/patch/2285/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
drivers/mtd/maps/Kconfig | 7 +
drivers/mtd/maps/Makefile | 1 +
drivers/mtd/maps/lantiq-flash.c | 251 +++++++++++++++++++++++++++++++++++++++
3 files changed, 259 insertions(+), 0 deletions(-)
create mode 100644 drivers/mtd/maps/lantiq-flash.c
--- a/drivers/mtd/maps/Kconfig
+++ b/drivers/mtd/maps/Kconfig
@@ -260,6 +260,13 @@ config MTD_BCM963XX
Support for parsing CFE image tag and creating MTD partitions on
Broadcom BCM63xx boards.
+config MTD_LANTIQ
+ tristate "Lantiq SoC NOR support"
+ depends on LANTIQ
+ select MTD_PARTITIONS
+ help
+ Support for NOR flash attached to the Lantiq SoC's External Bus Unit.
+
config MTD_DILNETPC
tristate "CFI Flash device mapped on DIL/Net PC"
depends on X86 && MTD_PARTITIONS && MTD_CFI_INTELEXT && BROKEN
--- a/drivers/mtd/maps/Makefile
+++ b/drivers/mtd/maps/Makefile
@@ -60,3 +60,4 @@ obj-$(CONFIG_MTD_VMU) += vmu-flash.o
obj-$(CONFIG_MTD_GPIO_ADDR) += gpio-addr-flash.o
obj-$(CONFIG_MTD_BCM963XX) += bcm963xx-flash.o
obj-$(CONFIG_MTD_LATCH_ADDR) += latch-addr-flash.o
+obj-$(CONFIG_MTD_LANTIQ) += lantiq-flash.o
--- /dev/null
+++ b/drivers/mtd/maps/lantiq-flash.c
@@ -0,0 +1,251 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2004 Liu Peng Infineon IFAP DC COM CPE
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/cfi.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+
+#include <lantiq_soc.h>
+#include <lantiq_platform.h>
+
+/*
+ * The NOR flash is connected to the same external bus unit (EBU) as PCI.
+ * To make PCI work we need to enable the endianness swapping for the address
+ * written to the EBU. This endianness swapping works for PCI correctly but
+ * fails for attached NOR devices. To workaround this we need to use a complex
+ * map. The workaround involves swapping all addresses whilst probing the chip.
+ * Once probing is complete we stop swapping the addresses but swizzle the
+ * unlock addresses to ensure that access to the NOR device works correctly.
+ */
+
+enum {
+ LTQ_NOR_PROBING,
+ LTQ_NOR_NORMAL
+};
+
+struct ltq_mtd {
+ struct resource *res;
+ struct mtd_info *mtd;
+ struct map_info *map;
+};
+
+static char ltq_map_name[] = "ltq_nor";
+
+static map_word
+ltq_read16(struct map_info *map, unsigned long adr)
+{
+ unsigned long flags;
+ map_word temp;
+
+ if (map->map_priv_1 == LTQ_NOR_PROBING)
+ adr ^= 2;
+ spin_lock_irqsave(&ebu_lock, flags);
+ temp.x[0] = *(u16 *)(map->virt + adr);
+ spin_unlock_irqrestore(&ebu_lock, flags);
+ return temp;
+}
+
+static void
+ltq_write16(struct map_info *map, map_word d, unsigned long adr)
+{
+ unsigned long flags;
+
+ if (map->map_priv_1 == LTQ_NOR_PROBING)
+ adr ^= 2;
+ spin_lock_irqsave(&ebu_lock, flags);
+ *(u16 *)(map->virt + adr) = d.x[0];
+ spin_unlock_irqrestore(&ebu_lock, flags);
+}
+
+/*
+ * The following 2 functions copy data between iomem and a cached memory
+ * section. As memcpy() makes use of pre-fetching we cannot use it here.
+ * The normal alternative of using memcpy_{to,from}io also makes use of
+ * memcpy() on MIPS so it is not applicable either. We are therefore stuck
+ * with having to use our own loop.
+ */
+static void
+ltq_copy_from(struct map_info *map, void *to,
+ unsigned long from, ssize_t len)
+{
+ unsigned char *f = (unsigned char *)map->virt + from;
+ unsigned char *t = (unsigned char *)to;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ebu_lock, flags);
+ while (len--)
+ *t++ = *f++;
+ spin_unlock_irqrestore(&ebu_lock, flags);
+}
+
+static void
+ltq_copy_to(struct map_info *map, unsigned long to,
+ const void *from, ssize_t len)
+{
+ unsigned char *f = (unsigned char *)from;
+ unsigned char *t = (unsigned char *)map->virt + to;
+ unsigned long flags;
+
+ spin_lock_irqsave(&ebu_lock, flags);
+ while (len--)
+ *t++ = *f++;
+ spin_unlock_irqrestore(&ebu_lock, flags);
+}
+
+static const char const *part_probe_types[] = { "cmdlinepart", NULL };
+
+static int __init
+ltq_mtd_probe(struct platform_device *pdev)
+{
+ struct physmap_flash_data *ltq_mtd_data = dev_get_platdata(&pdev->dev);
+ struct ltq_mtd *ltq_mtd;
+ struct mtd_partition *parts;
+ struct resource *res;
+ int nr_parts = 0;
+ struct cfi_private *cfi;
+ int err;
+
+ ltq_mtd = kzalloc(sizeof(struct ltq_mtd), GFP_KERNEL);
+ platform_set_drvdata(pdev, ltq_mtd);
+
+ ltq_mtd->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!ltq_mtd->res) {
+ dev_err(&pdev->dev, "failed to get memory resource");
+ err = -ENOENT;
+ goto err_out;
+ }
+
+ res = devm_request_mem_region(&pdev->dev, ltq_mtd->res->start,
+ resource_size(ltq_mtd->res), dev_name(&pdev->dev));
+ if (!ltq_mtd->res) {
+ dev_err(&pdev->dev, "failed to request mem resource");
+ err = -EBUSY;
+ goto err_out;
+ }
+
+ ltq_mtd->map = kzalloc(sizeof(struct map_info), GFP_KERNEL);
+ ltq_mtd->map->phys = res->start;
+ ltq_mtd->map->size = resource_size(res);
+ ltq_mtd->map->virt = devm_ioremap_nocache(&pdev->dev,
+ ltq_mtd->map->phys, ltq_mtd->map->size);
+ if (!ltq_mtd->map->virt) {
+ dev_err(&pdev->dev, "failed to ioremap!\n");
+ err = -ENOMEM;
+ goto err_free;
+ }
+
+ ltq_mtd->map->name = ltq_map_name;
+ ltq_mtd->map->bankwidth = 2;
+ ltq_mtd->map->read = ltq_read16;
+ ltq_mtd->map->write = ltq_write16;
+ ltq_mtd->map->copy_from = ltq_copy_from;
+ ltq_mtd->map->copy_to = ltq_copy_to;
+
+ ltq_mtd->map->map_priv_1 = LTQ_NOR_PROBING;
+ ltq_mtd->mtd = do_map_probe("cfi_probe", ltq_mtd->map);
+ ltq_mtd->map->map_priv_1 = LTQ_NOR_NORMAL;
+
+ if (!ltq_mtd->mtd) {
+ dev_err(&pdev->dev, "probing failed\n");
+ err = -ENXIO;
+ goto err_unmap;
+ }
+
+ ltq_mtd->mtd->owner = THIS_MODULE;
+
+ cfi = ltq_mtd->map->fldrv_priv;
+ cfi->addr_unlock1 ^= 1;
+ cfi->addr_unlock2 ^= 1;
+
+ nr_parts = parse_mtd_partitions(ltq_mtd->mtd,
+ part_probe_types, &parts, 0);
+ if (nr_parts > 0) {
+ dev_info(&pdev->dev,
+ "using %d partitions from cmdline", nr_parts);
+ } else {
+ nr_parts = ltq_mtd_data->nr_parts;
+ parts = ltq_mtd_data->parts;
+ }
+
+ err = add_mtd_partitions(ltq_mtd->mtd, parts, nr_parts);
+ if (err) {
+ dev_err(&pdev->dev, "failed to add partitions\n");
+ goto err_destroy;
+ }
+
+ return 0;
+
+err_destroy:
+ map_destroy(ltq_mtd->mtd);
+err_unmap:
+ iounmap(ltq_mtd->map->virt);
+err_free:
+ kfree(ltq_mtd->map);
+err_out:
+ kfree(ltq_mtd);
+ return err;
+}
+
+static int __devexit
+ltq_mtd_remove(struct platform_device *pdev)
+{
+ struct ltq_mtd *ltq_mtd = platform_get_drvdata(pdev);
+
+ if (ltq_mtd) {
+ if (ltq_mtd->mtd) {
+ del_mtd_partitions(ltq_mtd->mtd);
+ map_destroy(ltq_mtd->mtd);
+ }
+ if (ltq_mtd->map->virt)
+ iounmap(ltq_mtd->map->virt);
+ kfree(ltq_mtd->map);
+ kfree(ltq_mtd);
+ }
+ return 0;
+}
+
+static struct platform_driver ltq_mtd_driver = {
+ .remove = __devexit_p(ltq_mtd_remove),
+ .driver = {
+ .name = "ltq_nor",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init
+init_ltq_mtd(void)
+{
+ int ret = platform_driver_probe(&ltq_mtd_driver, ltq_mtd_probe);
+
+ if (ret)
+ pr_err("ltq_nor: error registering platform driver");
+ return ret;
+}
+
+static void __exit
+exit_ltq_mtd(void)
+{
+ platform_driver_unregister(&ltq_mtd_driver);
+}
+
+module_init(init_ltq_mtd);
+module_exit(exit_ltq_mtd);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
+MODULE_DESCRIPTION("Lantiq SoC NOR");

View File

@ -1,319 +0,0 @@
From 09e57348261c1ae0ff89c68679126fc76a28b2a2 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Wed, 30 Mar 2011 09:27:53 +0200
Subject: [PATCH 05/13] MIPS: Lantiq: Add platform device support
This patch adds the wrappers for registering our platform devices.
Signed-off-by: John Crispin <blogic@openwrt.org>
Signed-off-by: Ralph Hempel <ralph.hempel@lantiq.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/2254/
Patchwork: https://patchwork.linux-mips.org/patch/2360/
Patchwork: https://patchwork.linux-mips.org/patch/2359/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
arch/mips/lantiq/Makefile | 2 +-
arch/mips/lantiq/devices.c | 122 +++++++++++++++++++++++++++++++++++++++
arch/mips/lantiq/devices.h | 23 +++++++
arch/mips/lantiq/xway/Makefile | 2 +-
arch/mips/lantiq/xway/devices.c | 98 +++++++++++++++++++++++++++++++
arch/mips/lantiq/xway/devices.h | 18 ++++++
6 files changed, 263 insertions(+), 2 deletions(-)
create mode 100644 arch/mips/lantiq/devices.c
create mode 100644 arch/mips/lantiq/devices.h
create mode 100644 arch/mips/lantiq/xway/devices.c
create mode 100644 arch/mips/lantiq/xway/devices.h
--- a/arch/mips/lantiq/Makefile
+++ b/arch/mips/lantiq/Makefile
@@ -4,7 +4,7 @@
# under the terms of the GNU General Public License version 2 as published
# by the Free Software Foundation.
-obj-y := irq.o setup.o clk.o prom.o
+obj-y := irq.o setup.o clk.o prom.o devices.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
--- /dev/null
+++ b/arch/mips/lantiq/devices.c
@@ -0,0 +1,122 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/reboot.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/etherdevice.h>
+#include <linux/reboot.h>
+#include <linux/time.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+
+#include <lantiq_soc.h>
+
+#include "devices.h"
+
+/* nor flash */
+static struct resource ltq_nor_resource = {
+ .name = "nor",
+ .start = LTQ_FLASH_START,
+ .end = LTQ_FLASH_START + LTQ_FLASH_MAX - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device ltq_nor = {
+ .name = "ltq_nor",
+ .resource = &ltq_nor_resource,
+ .num_resources = 1,
+};
+
+void __init ltq_register_nor(struct physmap_flash_data *data)
+{
+ ltq_nor.dev.platform_data = data;
+ platform_device_register(&ltq_nor);
+}
+
+/* watchdog */
+static struct resource ltq_wdt_resource = {
+ .name = "watchdog",
+ .start = LTQ_WDT_BASE_ADDR,
+ .end = LTQ_WDT_BASE_ADDR + LTQ_WDT_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+void __init ltq_register_wdt(void)
+{
+ platform_device_register_simple("ltq_wdt", 0, &ltq_wdt_resource, 1);
+}
+
+/* asc ports */
+static struct resource ltq_asc0_resources[] = {
+ {
+ .name = "asc0",
+ .start = LTQ_ASC0_BASE_ADDR,
+ .end = LTQ_ASC0_BASE_ADDR + LTQ_ASC_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ IRQ_RES(tx, LTQ_ASC_TIR(0)),
+ IRQ_RES(rx, LTQ_ASC_RIR(0)),
+ IRQ_RES(err, LTQ_ASC_EIR(0)),
+};
+
+static struct resource ltq_asc1_resources[] = {
+ {
+ .name = "asc1",
+ .start = LTQ_ASC1_BASE_ADDR,
+ .end = LTQ_ASC1_BASE_ADDR + LTQ_ASC_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ IRQ_RES(tx, LTQ_ASC_TIR(1)),
+ IRQ_RES(rx, LTQ_ASC_RIR(1)),
+ IRQ_RES(err, LTQ_ASC_EIR(1)),
+};
+
+void __init ltq_register_asc(int port)
+{
+ switch (port) {
+ case 0:
+ platform_device_register_simple("ltq_asc", 0,
+ ltq_asc0_resources, ARRAY_SIZE(ltq_asc0_resources));
+ break;
+ case 1:
+ platform_device_register_simple("ltq_asc", 1,
+ ltq_asc1_resources, ARRAY_SIZE(ltq_asc1_resources));
+ break;
+ default:
+ break;
+ }
+}
+
+#ifdef CONFIG_PCI
+/* pci */
+static struct platform_device ltq_pci = {
+ .name = "ltq_pci",
+ .num_resources = 0,
+};
+
+void __init ltq_register_pci(struct ltq_pci_data *data)
+{
+ ltq_pci.dev.platform_data = data;
+ platform_device_register(&ltq_pci);
+}
+#else
+void __init ltq_register_pci(struct ltq_pci_data *data)
+{
+ pr_err("kernel is compiled without PCI support\n");
+}
+#endif
--- /dev/null
+++ b/arch/mips/lantiq/devices.h
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#ifndef _LTQ_DEVICES_H__
+#define _LTQ_DEVICES_H__
+
+#include <lantiq_platform.h>
+#include <linux/mtd/physmap.h>
+
+#define IRQ_RES(resname, irq) \
+ {.name = #resname, .start = (irq), .flags = IORESOURCE_IRQ}
+
+extern void ltq_register_nor(struct physmap_flash_data *data);
+extern void ltq_register_wdt(void);
+extern void ltq_register_asc(int port);
+extern void ltq_register_pci(struct ltq_pci_data *data);
+
+#endif
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -1,4 +1,4 @@
-obj-y := pmu.o ebu.o reset.o gpio.o
+obj-y := pmu.o ebu.o reset.o gpio.o devices.o
obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o
obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o
--- /dev/null
+++ b/arch/mips/lantiq/xway/devices.c
@@ -0,0 +1,98 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/mtd/physmap.h>
+#include <linux/kernel.h>
+#include <linux/reboot.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/etherdevice.h>
+#include <linux/reboot.h>
+#include <linux/time.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+
+#include <lantiq_soc.h>
+#include <lantiq_irq.h>
+#include <lantiq_platform.h>
+
+#include "devices.h"
+
+/* gpio */
+static struct resource ltq_gpio_resource[] = {
+ {
+ .name = "gpio0",
+ .start = LTQ_GPIO0_BASE_ADDR,
+ .end = LTQ_GPIO0_BASE_ADDR + LTQ_GPIO_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .name = "gpio1",
+ .start = LTQ_GPIO1_BASE_ADDR,
+ .end = LTQ_GPIO1_BASE_ADDR + LTQ_GPIO_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ }, {
+ .name = "gpio2",
+ .start = LTQ_GPIO2_BASE_ADDR,
+ .end = LTQ_GPIO2_BASE_ADDR + LTQ_GPIO_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ }
+};
+
+void __init ltq_register_gpio(void)
+{
+ platform_device_register_simple("ltq_gpio", 0,
+ &ltq_gpio_resource[0], 1);
+ platform_device_register_simple("ltq_gpio", 1,
+ &ltq_gpio_resource[1], 1);
+
+ /* AR9 and VR9 have an extra gpio block */
+ if (ltq_is_ar9() || ltq_is_vr9()) {
+ platform_device_register_simple("ltq_gpio", 2,
+ &ltq_gpio_resource[2], 1);
+ }
+}
+
+/* serial to parallel conversion */
+static struct resource ltq_stp_resource = {
+ .name = "stp",
+ .start = LTQ_STP_BASE_ADDR,
+ .end = LTQ_STP_BASE_ADDR + LTQ_STP_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+void __init ltq_register_gpio_stp(void)
+{
+ platform_device_register_simple("ltq_stp", 0, &ltq_stp_resource, 1);
+}
+
+/* asc ports - amazon se has its own serial mapping */
+static struct resource ltq_ase_asc_resources[] = {
+ {
+ .name = "asc0",
+ .start = LTQ_ASC1_BASE_ADDR,
+ .end = LTQ_ASC1_BASE_ADDR + LTQ_ASC_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ IRQ_RES(tx, LTQ_ASC_ASE_TIR),
+ IRQ_RES(rx, LTQ_ASC_ASE_RIR),
+ IRQ_RES(err, LTQ_ASC_ASE_EIR),
+};
+
+void __init ltq_register_ase_asc(void)
+{
+ platform_device_register_simple("ltq_asc", 0,
+ ltq_ase_asc_resources, ARRAY_SIZE(ltq_ase_asc_resources));
+}
--- /dev/null
+++ b/arch/mips/lantiq/xway/devices.h
@@ -0,0 +1,18 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#ifndef _LTQ_DEVICES_XWAY_H__
+#define _LTQ_DEVICES_XWAY_H__
+
+#include "../devices.h"
+
+extern void ltq_register_gpio(void);
+extern void ltq_register_gpio_stp(void);
+extern void ltq_register_ase_asc(void);
+
+#endif

View File

@ -1,170 +0,0 @@
From 52a5369d1067d4feddbfa7ff4486a77ac9a2971e Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Wed, 30 Mar 2011 09:27:54 +0200
Subject: [PATCH 06/13] MIPS: Lantiq: Add mips_machine support
This patch adds support for Gabor's mips_machine patch.
Signed-off-by: John Crispin <blogic@openwrt.org>
Signed-off-by: Ralph Hempel <ralph.hempel@lantiq.com>
Cc: Gabor Juhos <juhosg@openwrt.org>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/2251/
Patchwork: https://patchwork.linux-mips.org/patch/2358/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
arch/mips/Kconfig | 1 +
arch/mips/lantiq/machtypes.h | 18 ++++++++++++++++++
arch/mips/lantiq/prom.h | 1 +
arch/mips/lantiq/setup.c | 25 +++++++++++++++++++++++++
arch/mips/lantiq/xway/Makefile | 4 ++--
arch/mips/lantiq/xway/setup-ase.c | 19 +++++++++++++++++++
arch/mips/lantiq/xway/setup-xway.c | 20 ++++++++++++++++++++
7 files changed, 86 insertions(+), 2 deletions(-)
create mode 100644 arch/mips/lantiq/machtypes.h
create mode 100644 arch/mips/lantiq/xway/setup-ase.c
create mode 100644 arch/mips/lantiq/xway/setup-xway.c
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -228,6 +228,7 @@ config LANTIQ
select SWAP_IO_SPACE
select BOOT_RAW
select HAVE_CLK
+ select MIPS_MACHINE
config LASAT
bool "LASAT Networks platforms"
--- /dev/null
+++ b/arch/mips/lantiq/machtypes.h
@@ -0,0 +1,18 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#ifndef _LANTIQ_MACH_H__
+#define _LANTIQ_MACH_H__
+
+#include <asm/mips_machine.h>
+
+enum lantiq_mach_type {
+ LTQ_MACH_GENERIC = 0,
+};
+
+#endif
--- a/arch/mips/lantiq/prom.h
+++ b/arch/mips/lantiq/prom.h
@@ -20,5 +20,6 @@ struct ltq_soc_info {
};
extern void ltq_soc_detect(struct ltq_soc_info *i);
+extern void ltq_soc_setup(void);
#endif
--- a/arch/mips/lantiq/setup.c
+++ b/arch/mips/lantiq/setup.c
@@ -14,6 +14,12 @@
#include <lantiq_soc.h>
+#include "machtypes.h"
+#include "devices.h"
+#include "prom.h"
+
+unsigned long physical_memsize = 0L;
+
void __init plat_mem_setup(void)
{
/* assume 16M as default incase uboot fails to pass proper ramsize */
@@ -32,10 +38,32 @@ void __init plat_mem_setup(void)
if (!strncmp(e, "memsize=", 8)) {
e += 8;
if (strict_strtoul(e, 0, &memsize))
- pr_warn("bad memsize specified\n");
+ pr_warning("bad memsize specified\n");
}
envp++;
}
memsize *= 1024 * 1024;
add_memory_region(0x00000000, memsize, BOOT_MEM_RAM);
+ physical_memsize = memsize;
+}
+
+static int __init
+lantiq_setup(void)
+{
+ ltq_soc_setup();
+ mips_machine_setup();
+ return 0;
}
+
+arch_initcall(lantiq_setup);
+
+static void __init
+lantiq_generic_init(void)
+{
+ /* Nothing to do */
+}
+
+MIPS_MACHINE(LTQ_MACH_GENERIC,
+ "Generic",
+ "Generic Lantiq based board",
+ lantiq_generic_init);
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -1,4 +1,4 @@
obj-y := pmu.o ebu.o reset.o gpio.o devices.o
-obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o
-obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o
+obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o setup-xway.o
+obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o setup-ase.o
--- /dev/null
+++ b/arch/mips/lantiq/xway/setup-ase.c
@@ -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 version 2 as published
+ * by the Free Software Foundation.
+ *
+ * Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ */
+
+#include <lantiq_soc.h>
+
+#include "../prom.h"
+#include "devices.h"
+
+void __init ltq_soc_setup(void)
+{
+ ltq_register_ase_asc();
+ ltq_register_gpio();
+ ltq_register_wdt();
+}
--- /dev/null
+++ b/arch/mips/lantiq/xway/setup-xway.c
@@ -0,0 +1,20 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ */
+
+#include <lantiq_soc.h>
+
+#include "../prom.h"
+#include "devices.h"
+
+void __init ltq_soc_setup(void)
+{
+ ltq_register_asc(0);
+ ltq_register_asc(1);
+ ltq_register_gpio();
+ ltq_register_wdt();
+}

View File

@ -1,212 +0,0 @@
From ab2182fc419548455d03979683eb0e92c372ed79 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Wed, 30 Mar 2011 09:27:55 +0200
Subject: [PATCH 07/13] MIPS: Lantiq: Add machtypes for lantiq eval kits
This patch adds mach specific code for the Lantiq EASY50712/50601 evaluation
boards
Signed-off-by: John Crispin <blogic@openwrt.org>
Signed-off-by: Ralph Hempel <ralph.hempel@lantiq.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/2255/
Patchwork: https://patchwork.linux-mips.org/patch/2361/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
arch/mips/lantiq/Kconfig | 2 +
arch/mips/lantiq/machtypes.h | 2 +
arch/mips/lantiq/xway/Kconfig | 23 +++++++++++
arch/mips/lantiq/xway/Makefile | 3 +
arch/mips/lantiq/xway/mach-easy50601.c | 57 ++++++++++++++++++++++++++
arch/mips/lantiq/xway/mach-easy50712.c | 68 ++++++++++++++++++++++++++++++++
6 files changed, 155 insertions(+), 0 deletions(-)
create mode 100644 arch/mips/lantiq/xway/Kconfig
create mode 100644 arch/mips/lantiq/xway/mach-easy50601.c
create mode 100644 arch/mips/lantiq/xway/mach-easy50712.c
--- a/arch/mips/lantiq/Kconfig
+++ b/arch/mips/lantiq/Kconfig
@@ -18,4 +18,6 @@ config SOC_XWAY
select HW_HAS_PCI
endchoice
+source "arch/mips/lantiq/xway/Kconfig"
+
endif
--- a/arch/mips/lantiq/machtypes.h
+++ b/arch/mips/lantiq/machtypes.h
@@ -13,6 +13,8 @@
enum lantiq_mach_type {
LTQ_MACH_GENERIC = 0,
+ LTQ_MACH_EASY50712, /* Danube evaluation board */
+ LTQ_MACH_EASY50601, /* Amazon SE evaluation board */
};
#endif
--- /dev/null
+++ b/arch/mips/lantiq/xway/Kconfig
@@ -0,0 +1,23 @@
+if SOC_XWAY
+
+menu "MIPS Machine"
+
+config LANTIQ_MACH_EASY50712
+ bool "Easy50712 - Danube"
+ default y
+
+endmenu
+
+endif
+
+if SOC_AMAZON_SE
+
+menu "MIPS Machine"
+
+config LANTIQ_MACH_EASY50601
+ bool "Easy50601 - Amazon SE"
+ default y
+
+endmenu
+
+endif
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -2,3 +2,6 @@ obj-y := pmu.o ebu.o reset.o gpio.o devi
obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o setup-xway.o
obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o setup-ase.o
+
+obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o
+obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o
--- /dev/null
+++ b/arch/mips/lantiq/xway/mach-easy50601.c
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/input.h>
+
+#include <lantiq.h>
+
+#include "../machtypes.h"
+#include "devices.h"
+
+static struct mtd_partition easy50601_partitions[] = {
+ {
+ .name = "uboot",
+ .offset = 0x0,
+ .size = 0x10000,
+ },
+ {
+ .name = "uboot_env",
+ .offset = 0x10000,
+ .size = 0x10000,
+ },
+ {
+ .name = "linux",
+ .offset = 0x20000,
+ .size = 0xE0000,
+ },
+ {
+ .name = "rootfs",
+ .offset = 0x100000,
+ .size = 0x300000,
+ },
+};
+
+static struct physmap_flash_data easy50601_flash_data = {
+ .nr_parts = ARRAY_SIZE(easy50601_partitions),
+ .parts = easy50601_partitions,
+};
+
+static void __init easy50601_init(void)
+{
+ ltq_register_nor(&easy50601_flash_data);
+}
+
+MIPS_MACHINE(LTQ_MACH_EASY50601,
+ "EASY50601",
+ "EASY50601 Eval Board",
+ easy50601_init);
--- /dev/null
+++ b/arch/mips/lantiq/xway/mach-easy50712.c
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/input.h>
+
+#include <lantiq_soc.h>
+#include <irq.h>
+
+#include "../machtypes.h"
+#include "devices.h"
+
+static struct mtd_partition easy50712_partitions[] = {
+ {
+ .name = "uboot",
+ .offset = 0x0,
+ .size = 0x10000,
+ },
+ {
+ .name = "uboot_env",
+ .offset = 0x10000,
+ .size = 0x10000,
+ },
+ {
+ .name = "linux",
+ .offset = 0x20000,
+ .size = 0xe0000,
+ },
+ {
+ .name = "rootfs",
+ .offset = 0x100000,
+ .size = 0x300000,
+ },
+};
+
+static struct physmap_flash_data easy50712_flash_data = {
+ .nr_parts = ARRAY_SIZE(easy50712_partitions),
+ .parts = easy50712_partitions,
+};
+
+static struct ltq_pci_data ltq_pci_data = {
+ .clock = PCI_CLOCK_INT,
+ .gpio = PCI_GNT1 | PCI_REQ1,
+ .irq = {
+ [14] = INT_NUM_IM0_IRL0 + 22,
+ },
+};
+
+static void __init easy50712_init(void)
+{
+ ltq_register_gpio_stp();
+ ltq_register_nor(&easy50712_flash_data);
+ ltq_register_pci(&ltq_pci_data);
+}
+
+MIPS_MACHINE(LTQ_MACH_EASY50712,
+ "EASY50712",
+ "EASY50712 Eval Board",
+ easy50712_init);

View File

@ -1,319 +0,0 @@
From f9391211e47cdcc31f341d710efef4b3b46c333d Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Wed, 30 Mar 2011 09:27:56 +0200
Subject: [PATCH 08/13] MIPS: Lantiq: Add more gpio drivers
The XWAY family allows to extend the number of gpios by using shift registers or latches. This patch adds the 2 drivers needed for this. The extended gpios are output only.
[ralf@linux-mips.org: Fixed ltq_stp_probe section() attributes.]
Signed-off-by: John Crispin <blogic@openwrt.org>
Signed-off-by: Ralph Hempel <ralph.hempel@lantiq.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/2258/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
arch/mips/lantiq/xway/Makefile | 2 +-
arch/mips/lantiq/xway/gpio_ebu.c | 126 ++++++++++++++++++++++++++++++
arch/mips/lantiq/xway/gpio_stp.c | 157 ++++++++++++++++++++++++++++++++++++++
3 files changed, 284 insertions(+), 1 deletions(-)
create mode 100644 arch/mips/lantiq/xway/gpio_ebu.c
create mode 100644 arch/mips/lantiq/xway/gpio_stp.c
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -1,4 +1,4 @@
-obj-y := pmu.o ebu.o reset.o gpio.o devices.o
+obj-y := pmu.o ebu.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o
obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o setup-xway.o
obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o setup-ase.o
--- /dev/null
+++ b/arch/mips/lantiq/xway/gpio_ebu.c
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/gpio.h>
+#include <linux/io.h>
+
+#include <lantiq_soc.h>
+
+/*
+ * By attaching hardware latches to the EBU it is possible to create output
+ * only gpios. This driver configures a special memory address, which when
+ * written to outputs 16 bit to the latches.
+ */
+
+#define LTQ_EBU_BUSCON 0x1e7ff /* 16 bit access, slowest timing */
+#define LTQ_EBU_WP 0x80000000 /* write protect bit */
+
+/* we keep a shadow value of the last value written to the ebu */
+static int ltq_ebu_gpio_shadow = 0x0;
+static void __iomem *ltq_ebu_gpio_membase;
+
+static void ltq_ebu_apply(void)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ebu_lock, flags);
+ ltq_ebu_w32(LTQ_EBU_BUSCON, LTQ_EBU_BUSCON1);
+ *((__u16 *)ltq_ebu_gpio_membase) = ltq_ebu_gpio_shadow;
+ ltq_ebu_w32(LTQ_EBU_BUSCON | LTQ_EBU_WP, LTQ_EBU_BUSCON1);
+ spin_unlock_irqrestore(&ebu_lock, flags);
+}
+
+static void ltq_ebu_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ if (value)
+ ltq_ebu_gpio_shadow |= (1 << offset);
+ else
+ ltq_ebu_gpio_shadow &= ~(1 << offset);
+ ltq_ebu_apply();
+}
+
+static int ltq_ebu_direction_output(struct gpio_chip *chip, unsigned offset,
+ int value)
+{
+ ltq_ebu_set(chip, offset, value);
+
+ return 0;
+}
+
+static struct gpio_chip ltq_ebu_chip = {
+ .label = "ltq_ebu",
+ .direction_output = ltq_ebu_direction_output,
+ .set = ltq_ebu_set,
+ .base = 72,
+ .ngpio = 16,
+ .can_sleep = 1,
+ .owner = THIS_MODULE,
+};
+
+static int ltq_ebu_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ if (!res) {
+ dev_err(&pdev->dev, "failed to get memory resource\n");
+ return -ENOENT;
+ }
+
+ res = devm_request_mem_region(&pdev->dev, res->start,
+ resource_size(res), dev_name(&pdev->dev));
+ if (!res) {
+ dev_err(&pdev->dev, "failed to request memory resource\n");
+ return -EBUSY;
+ }
+
+ ltq_ebu_gpio_membase = devm_ioremap_nocache(&pdev->dev, res->start,
+ resource_size(res));
+ if (!ltq_ebu_gpio_membase) {
+ dev_err(&pdev->dev, "Failed to ioremap mem region\n");
+ return -ENOMEM;
+ }
+
+ /* grab the default shadow value passed form the platform code */
+ ltq_ebu_gpio_shadow = (unsigned int) pdev->dev.platform_data;
+
+ /* tell the ebu controller which memory address we will be using */
+ ltq_ebu_w32(pdev->resource->start | 0x1, LTQ_EBU_ADDRSEL1);
+
+ /* write protect the region */
+ ltq_ebu_w32(LTQ_EBU_BUSCON | LTQ_EBU_WP, LTQ_EBU_BUSCON1);
+
+ ret = gpiochip_add(&ltq_ebu_chip);
+ if (!ret)
+ ltq_ebu_apply();
+ return ret;
+}
+
+static struct platform_driver ltq_ebu_driver = {
+ .probe = ltq_ebu_probe,
+ .driver = {
+ .name = "ltq_ebu",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init ltq_ebu_init(void)
+{
+ int ret = platform_driver_register(&ltq_ebu_driver);
+
+ if (ret)
+ pr_info("ltq_ebu : Error registering platfom driver!");
+ return ret;
+}
+
+postcore_initcall(ltq_ebu_init);
--- /dev/null
+++ b/arch/mips/lantiq/xway/gpio_stp.c
@@ -0,0 +1,157 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2007 John Crispin <blogic@openwrt.org>
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+
+#include <lantiq_soc.h>
+
+#define LTQ_STP_CON0 0x00
+#define LTQ_STP_CON1 0x04
+#define LTQ_STP_CPU0 0x08
+#define LTQ_STP_CPU1 0x0C
+#define LTQ_STP_AR 0x10
+
+#define LTQ_STP_CON_SWU (1 << 31)
+#define LTQ_STP_2HZ 0
+#define LTQ_STP_4HZ (1 << 23)
+#define LTQ_STP_8HZ (2 << 23)
+#define LTQ_STP_10HZ (3 << 23)
+#define LTQ_STP_SPEED_MASK (0xf << 23)
+#define LTQ_STP_UPD_FPI (1 << 31)
+#define LTQ_STP_UPD_MASK (3 << 30)
+#define LTQ_STP_ADSL_SRC (3 << 24)
+
+#define LTQ_STP_GROUP0 (1 << 0)
+
+#define LTQ_STP_RISING 0
+#define LTQ_STP_FALLING (1 << 26)
+#define LTQ_STP_EDGE_MASK (1 << 26)
+
+#define ltq_stp_r32(reg) __raw_readl(ltq_stp_membase + reg)
+#define ltq_stp_w32(val, reg) __raw_writel(val, ltq_stp_membase + reg)
+#define ltq_stp_w32_mask(clear, set, reg) \
+ ltq_w32((ltq_r32(ltq_stp_membase + reg) & ~(clear)) | (set), \
+ ltq_stp_membase + (reg))
+
+static int ltq_stp_shadow = 0xffff;
+static void __iomem *ltq_stp_membase;
+
+static void ltq_stp_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ if (value)
+ ltq_stp_shadow |= (1 << offset);
+ else
+ ltq_stp_shadow &= ~(1 << offset);
+ ltq_stp_w32(ltq_stp_shadow, LTQ_STP_CPU0);
+}
+
+static int ltq_stp_direction_output(struct gpio_chip *chip, unsigned offset,
+ int value)
+{
+ ltq_stp_set(chip, offset, value);
+
+ return 0;
+}
+
+static struct gpio_chip ltq_stp_chip = {
+ .label = "ltq_stp",
+ .direction_output = ltq_stp_direction_output,
+ .set = ltq_stp_set,
+ .base = 48,
+ .ngpio = 24,
+ .can_sleep = 1,
+ .owner = THIS_MODULE,
+};
+
+static int ltq_stp_hw_init(void)
+{
+ /* the 3 pins used to control the external stp */
+ ltq_gpio_request(4, 1, 0, 1, "stp-st");
+ ltq_gpio_request(5, 1, 0, 1, "stp-d");
+ ltq_gpio_request(6, 1, 0, 1, "stp-sh");
+
+ /* sane defaults */
+ ltq_stp_w32(0, LTQ_STP_AR);
+ ltq_stp_w32(0, LTQ_STP_CPU0);
+ ltq_stp_w32(0, LTQ_STP_CPU1);
+ ltq_stp_w32(LTQ_STP_CON_SWU, LTQ_STP_CON0);
+ ltq_stp_w32(0, LTQ_STP_CON1);
+
+ /* rising or falling edge */
+ ltq_stp_w32_mask(LTQ_STP_EDGE_MASK, LTQ_STP_FALLING, LTQ_STP_CON0);
+
+ /* per default stp 15-0 are set */
+ ltq_stp_w32_mask(0, LTQ_STP_GROUP0, LTQ_STP_CON1);
+
+ /* stp are update periodically by the FPI bus */
+ ltq_stp_w32_mask(LTQ_STP_UPD_MASK, LTQ_STP_UPD_FPI, LTQ_STP_CON1);
+
+ /* set stp update speed */
+ ltq_stp_w32_mask(LTQ_STP_SPEED_MASK, LTQ_STP_8HZ, LTQ_STP_CON1);
+
+ /* tell the hardware that pin (led) 0 and 1 are controlled
+ * by the dsl arc
+ */
+ ltq_stp_w32_mask(0, LTQ_STP_ADSL_SRC, LTQ_STP_CON0);
+
+ ltq_pmu_enable(PMU_LED);
+ return 0;
+}
+
+static int __devinit ltq_stp_probe(struct platform_device *pdev)
+{
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ int ret = 0;
+
+ if (!res)
+ return -ENOENT;
+ res = devm_request_mem_region(&pdev->dev, res->start,
+ resource_size(res), dev_name(&pdev->dev));
+ if (!res) {
+ dev_err(&pdev->dev, "failed to request STP memory\n");
+ return -EBUSY;
+ }
+ ltq_stp_membase = devm_ioremap_nocache(&pdev->dev, res->start,
+ resource_size(res));
+ if (!ltq_stp_membase) {
+ dev_err(&pdev->dev, "failed to remap STP memory\n");
+ return -ENOMEM;
+ }
+ ret = gpiochip_add(&ltq_stp_chip);
+ if (!ret)
+ ret = ltq_stp_hw_init();
+
+ return ret;
+}
+
+static struct platform_driver ltq_stp_driver = {
+ .probe = ltq_stp_probe,
+ .driver = {
+ .name = "ltq_stp",
+ .owner = THIS_MODULE,
+ },
+};
+
+int __init ltq_stp_init(void)
+{
+ int ret = platform_driver_register(&ltq_stp_driver);
+
+ if (ret)
+ pr_info("ltq_stp: error registering platfom driver");
+ return ret;
+}
+
+postcore_initcall(ltq_stp_init);

View File

@ -1,804 +0,0 @@
From 1d2b44b1afa3ef081cd817dbf947d48eb8f5d21a Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Tue, 5 Apr 2011 14:10:57 +0200
Subject: [PATCH 09/13] SERIAL: Lantiq: Add driver for MIPS Lantiq SOCs.
Signed-off-by: John Crispin <blogic@openwrt.org>
Signed-off-by: Ralph Hempel <ralph.hempel@lantiq.com>
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Cc: alan@lxorguk.ukuu.org.uk
Cc: linux-mips@linux-mips.org
Cc: linux-serial@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/2269/
Acked-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
drivers/tty/serial/Kconfig | 8 +
drivers/tty/serial/Makefile | 1 +
drivers/tty/serial/lantiq.c | 756 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 765 insertions(+), 0 deletions(-)
create mode 100644 drivers/tty/serial/lantiq.c
--- /dev/null
+++ b/drivers/tty/serial/lantiq.c
@@ -0,0 +1,756 @@
+/*
+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
+ *
+ * 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
+ *
+ * Copyright (C) 2004 Infineon IFAP DC COM CPE
+ * Copyright (C) 2007 Felix Fietkau <nbd@openwrt.org>
+ * Copyright (C) 2007 John Crispin <blogic@openwrt.org>
+ * Copyright (C) 2010 Thomas Langer, <thomas.langer@lantiq.com>
+ */
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/sysrq.h>
+#include <linux/device.h>
+#include <linux/tty.h>
+#include <linux/tty_flip.h>
+#include <linux/serial_core.h>
+#include <linux/serial.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+
+#include <lantiq_soc.h>
+
+#define PORT_LTQ_ASC 111
+#define MAXPORTS 2
+#define UART_DUMMY_UER_RX 1
+#define DRVNAME "ltq_asc"
+#ifdef __BIG_ENDIAN
+#define LTQ_ASC_TBUF (0x0020 + 3)
+#define LTQ_ASC_RBUF (0x0024 + 3)
+#else
+#define LTQ_ASC_TBUF 0x0020
+#define LTQ_ASC_RBUF 0x0024
+#endif
+#define LTQ_ASC_FSTAT 0x0048
+#define LTQ_ASC_WHBSTATE 0x0018
+#define LTQ_ASC_STATE 0x0014
+#define LTQ_ASC_IRNCR 0x00F8
+#define LTQ_ASC_CLC 0x0000
+#define LTQ_ASC_ID 0x0008
+#define LTQ_ASC_PISEL 0x0004
+#define LTQ_ASC_TXFCON 0x0044
+#define LTQ_ASC_RXFCON 0x0040
+#define LTQ_ASC_CON 0x0010
+#define LTQ_ASC_BG 0x0050
+#define LTQ_ASC_IRNREN 0x00F4
+
+#define ASC_IRNREN_TX 0x1
+#define ASC_IRNREN_RX 0x2
+#define ASC_IRNREN_ERR 0x4
+#define ASC_IRNREN_TX_BUF 0x8
+#define ASC_IRNCR_TIR 0x1
+#define ASC_IRNCR_RIR 0x2
+#define ASC_IRNCR_EIR 0x4
+
+#define ASCOPT_CSIZE 0x3
+#define TXFIFO_FL 1
+#define RXFIFO_FL 1
+#define ASCCLC_DISS 0x2
+#define ASCCLC_RMCMASK 0x0000FF00
+#define ASCCLC_RMCOFFSET 8
+#define ASCCON_M_8ASYNC 0x0
+#define ASCCON_M_7ASYNC 0x2
+#define ASCCON_ODD 0x00000020
+#define ASCCON_STP 0x00000080
+#define ASCCON_BRS 0x00000100
+#define ASCCON_FDE 0x00000200
+#define ASCCON_R 0x00008000
+#define ASCCON_FEN 0x00020000
+#define ASCCON_ROEN 0x00080000
+#define ASCCON_TOEN 0x00100000
+#define ASCSTATE_PE 0x00010000
+#define ASCSTATE_FE 0x00020000
+#define ASCSTATE_ROE 0x00080000
+#define ASCSTATE_ANY (ASCSTATE_ROE|ASCSTATE_PE|ASCSTATE_FE)
+#define ASCWHBSTATE_CLRREN 0x00000001
+#define ASCWHBSTATE_SETREN 0x00000002
+#define ASCWHBSTATE_CLRPE 0x00000004
+#define ASCWHBSTATE_CLRFE 0x00000008
+#define ASCWHBSTATE_CLRROE 0x00000020
+#define ASCTXFCON_TXFEN 0x0001
+#define ASCTXFCON_TXFFLU 0x0002
+#define ASCTXFCON_TXFITLMASK 0x3F00
+#define ASCTXFCON_TXFITLOFF 8
+#define ASCRXFCON_RXFEN 0x0001
+#define ASCRXFCON_RXFFLU 0x0002
+#define ASCRXFCON_RXFITLMASK 0x3F00
+#define ASCRXFCON_RXFITLOFF 8
+#define ASCFSTAT_RXFFLMASK 0x003F
+#define ASCFSTAT_TXFFLMASK 0x3F00
+#define ASCFSTAT_TXFREEMASK 0x3F000000
+#define ASCFSTAT_TXFREEOFF 24
+
+static void lqasc_tx_chars(struct uart_port *port);
+static struct ltq_uart_port *lqasc_port[MAXPORTS];
+static struct uart_driver lqasc_reg;
+static DEFINE_SPINLOCK(ltq_asc_lock);
+
+struct ltq_uart_port {
+ struct uart_port port;
+ struct clk *clk;
+ unsigned int tx_irq;
+ unsigned int rx_irq;
+ unsigned int err_irq;
+};
+
+static inline struct
+ltq_uart_port *to_ltq_uart_port(struct uart_port *port)
+{
+ return container_of(port, struct ltq_uart_port, port);
+}
+
+static void
+lqasc_stop_tx(struct uart_port *port)
+{
+ return;
+}
+
+static void
+lqasc_start_tx(struct uart_port *port)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&ltq_asc_lock, flags);
+ lqasc_tx_chars(port);
+ spin_unlock_irqrestore(&ltq_asc_lock, flags);
+ return;
+}
+
+static void
+lqasc_stop_rx(struct uart_port *port)
+{
+ ltq_w32(ASCWHBSTATE_CLRREN, port->membase + LTQ_ASC_WHBSTATE);
+}
+
+static void
+lqasc_enable_ms(struct uart_port *port)
+{
+}
+
+static int
+lqasc_rx_chars(struct uart_port *port)
+{
+ struct tty_struct *tty = tty_port_tty_get(&port->state->port);
+ unsigned int ch = 0, rsr = 0, fifocnt;
+
+ if (!tty) {
+ dev_dbg(port->dev, "%s:tty is busy now", __func__);
+ return -EBUSY;
+ }
+ fifocnt =
+ ltq_r32(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_RXFFLMASK;
+ while (fifocnt--) {
+ u8 flag = TTY_NORMAL;
+ ch = ltq_r8(port->membase + LTQ_ASC_RBUF);
+ rsr = (ltq_r32(port->membase + LTQ_ASC_STATE)
+ & ASCSTATE_ANY) | UART_DUMMY_UER_RX;
+ tty_flip_buffer_push(tty);
+ port->icount.rx++;
+
+ /*
+ * Note that the error handling code is
+ * out of the main execution path
+ */
+ if (rsr & ASCSTATE_ANY) {
+ if (rsr & ASCSTATE_PE) {
+ port->icount.parity++;
+ ltq_w32_mask(0, ASCWHBSTATE_CLRPE,
+ port->membase + LTQ_ASC_WHBSTATE);
+ } else if (rsr & ASCSTATE_FE) {
+ port->icount.frame++;
+ ltq_w32_mask(0, ASCWHBSTATE_CLRFE,
+ port->membase + LTQ_ASC_WHBSTATE);
+ }
+ if (rsr & ASCSTATE_ROE) {
+ port->icount.overrun++;
+ ltq_w32_mask(0, ASCWHBSTATE_CLRROE,
+ port->membase + LTQ_ASC_WHBSTATE);
+ }
+
+ rsr &= port->read_status_mask;
+
+ if (rsr & ASCSTATE_PE)
+ flag = TTY_PARITY;
+ else if (rsr & ASCSTATE_FE)
+ flag = TTY_FRAME;
+ }
+
+ if ((rsr & port->ignore_status_mask) == 0)
+ tty_insert_flip_char(tty, ch, flag);
+
+ if (rsr & ASCSTATE_ROE)
+ /*
+ * Overrun is special, since it's reported
+ * immediately, and doesn't affect the current
+ * character
+ */
+ tty_insert_flip_char(tty, 0, TTY_OVERRUN);
+ }
+ if (ch != 0)
+ tty_flip_buffer_push(tty);
+ tty_kref_put(tty);
+ return 0;
+}
+
+static void
+lqasc_tx_chars(struct uart_port *port)
+{
+ struct circ_buf *xmit = &port->state->xmit;
+ if (uart_tx_stopped(port)) {
+ lqasc_stop_tx(port);
+ return;
+ }
+
+ while (((ltq_r32(port->membase + LTQ_ASC_FSTAT) &
+ ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF) != 0) {
+ if (port->x_char) {
+ ltq_w8(port->x_char, port->membase + LTQ_ASC_TBUF);
+ port->icount.tx++;
+ port->x_char = 0;
+ continue;
+ }
+
+ if (uart_circ_empty(xmit))
+ break;
+
+ ltq_w8(port->state->xmit.buf[port->state->xmit.tail],
+ port->membase + LTQ_ASC_TBUF);
+ xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
+ port->icount.tx++;
+ }
+
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
+ uart_write_wakeup(port);
+}
+
+static irqreturn_t
+lqasc_tx_int(int irq, void *_port)
+{
+ unsigned long flags;
+ struct uart_port *port = (struct uart_port *)_port;
+ spin_lock_irqsave(&ltq_asc_lock, flags);
+ ltq_w32(ASC_IRNCR_TIR, port->membase + LTQ_ASC_IRNCR);
+ spin_unlock_irqrestore(&ltq_asc_lock, flags);
+ lqasc_start_tx(port);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t
+lqasc_err_int(int irq, void *_port)
+{
+ unsigned long flags;
+ struct uart_port *port = (struct uart_port *)_port;
+ spin_lock_irqsave(&ltq_asc_lock, flags);
+ /* clear any pending interrupts */
+ ltq_w32_mask(0, ASCWHBSTATE_CLRPE | ASCWHBSTATE_CLRFE |
+ ASCWHBSTATE_CLRROE, port->membase + LTQ_ASC_WHBSTATE);
+ spin_unlock_irqrestore(&ltq_asc_lock, flags);
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t
+lqasc_rx_int(int irq, void *_port)
+{
+ unsigned long flags;
+ struct uart_port *port = (struct uart_port *)_port;
+ spin_lock_irqsave(&ltq_asc_lock, flags);
+ ltq_w32(ASC_IRNCR_RIR, port->membase + LTQ_ASC_IRNCR);
+ lqasc_rx_chars(port);
+ spin_unlock_irqrestore(&ltq_asc_lock, flags);
+ return IRQ_HANDLED;
+}
+
+static unsigned int
+lqasc_tx_empty(struct uart_port *port)
+{
+ int status;
+ status = ltq_r32(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_TXFFLMASK;
+ return status ? 0 : TIOCSER_TEMT;
+}
+
+static unsigned int
+lqasc_get_mctrl(struct uart_port *port)
+{
+ return TIOCM_CTS | TIOCM_CAR | TIOCM_DSR;
+}
+
+static void
+lqasc_set_mctrl(struct uart_port *port, u_int mctrl)
+{
+}
+
+static void
+lqasc_break_ctl(struct uart_port *port, int break_state)
+{
+}
+
+static int
+lqasc_startup(struct uart_port *port)
+{
+ struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
+ int retval;
+
+ port->uartclk = clk_get_rate(ltq_port->clk);
+
+ ltq_w32_mask(ASCCLC_DISS | ASCCLC_RMCMASK, (1 << ASCCLC_RMCOFFSET),
+ port->membase + LTQ_ASC_CLC);
+
+ ltq_w32(0, port->membase + LTQ_ASC_PISEL);
+ ltq_w32(
+ ((TXFIFO_FL << ASCTXFCON_TXFITLOFF) & ASCTXFCON_TXFITLMASK) |
+ ASCTXFCON_TXFEN | ASCTXFCON_TXFFLU,
+ port->membase + LTQ_ASC_TXFCON);
+ ltq_w32(
+ ((RXFIFO_FL << ASCRXFCON_RXFITLOFF) & ASCRXFCON_RXFITLMASK)
+ | ASCRXFCON_RXFEN | ASCRXFCON_RXFFLU,
+ port->membase + LTQ_ASC_RXFCON);
+ /* make sure other settings are written to hardware before
+ * setting enable bits
+ */
+ wmb();
+ ltq_w32_mask(0, ASCCON_M_8ASYNC | ASCCON_FEN | ASCCON_TOEN |
+ ASCCON_ROEN, port->membase + LTQ_ASC_CON);
+
+ retval = request_irq(ltq_port->tx_irq, lqasc_tx_int,
+ IRQF_DISABLED, "asc_tx", port);
+ if (retval) {
+ pr_err("failed to request lqasc_tx_int\n");
+ return retval;
+ }
+
+ retval = request_irq(ltq_port->rx_irq, lqasc_rx_int,
+ IRQF_DISABLED, "asc_rx", port);
+ if (retval) {
+ pr_err("failed to request lqasc_rx_int\n");
+ goto err1;
+ }
+
+ retval = request_irq(ltq_port->err_irq, lqasc_err_int,
+ IRQF_DISABLED, "asc_err", port);
+ if (retval) {
+ pr_err("failed to request lqasc_err_int\n");
+ goto err2;
+ }
+
+ ltq_w32(ASC_IRNREN_RX | ASC_IRNREN_ERR | ASC_IRNREN_TX,
+ port->membase + LTQ_ASC_IRNREN);
+ return 0;
+
+err2:
+ free_irq(ltq_port->rx_irq, port);
+err1:
+ free_irq(ltq_port->tx_irq, port);
+ return retval;
+}
+
+static void
+lqasc_shutdown(struct uart_port *port)
+{
+ struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
+ free_irq(ltq_port->tx_irq, port);
+ free_irq(ltq_port->rx_irq, port);
+ free_irq(ltq_port->err_irq, port);
+
+ ltq_w32(0, port->membase + LTQ_ASC_CON);
+ ltq_w32_mask(ASCRXFCON_RXFEN, ASCRXFCON_RXFFLU,
+ port->membase + LTQ_ASC_RXFCON);
+ ltq_w32_mask(ASCTXFCON_TXFEN, ASCTXFCON_TXFFLU,
+ port->membase + LTQ_ASC_TXFCON);
+}
+
+static void
+lqasc_set_termios(struct uart_port *port,
+ struct ktermios *new, struct ktermios *old)
+{
+ unsigned int cflag;
+ unsigned int iflag;
+ unsigned int divisor;
+ unsigned int baud;
+ unsigned int con = 0;
+ unsigned long flags;
+
+ cflag = new->c_cflag;
+ iflag = new->c_iflag;
+
+ switch (cflag & CSIZE) {
+ case CS7:
+ con = ASCCON_M_7ASYNC;
+ break;
+
+ case CS5:
+ case CS6:
+ default:
+ new->c_cflag &= ~ CSIZE;
+ new->c_cflag |= CS8;
+ con = ASCCON_M_8ASYNC;
+ break;
+ }
+
+ cflag &= ~CMSPAR; /* Mark/Space parity is not supported */
+
+ if (cflag & CSTOPB)
+ con |= ASCCON_STP;
+
+ if (cflag & PARENB) {
+ if (!(cflag & PARODD))
+ con &= ~ASCCON_ODD;
+ else
+ con |= ASCCON_ODD;
+ }
+
+ port->read_status_mask = ASCSTATE_ROE;
+ if (iflag & INPCK)
+ port->read_status_mask |= ASCSTATE_FE | ASCSTATE_PE;
+
+ port->ignore_status_mask = 0;
+ if (iflag & IGNPAR)
+ port->ignore_status_mask |= ASCSTATE_FE | ASCSTATE_PE;
+
+ if (iflag & IGNBRK) {
+ /*
+ * If we're ignoring parity and break indicators,
+ * ignore overruns too (for real raw support).
+ */
+ if (iflag & IGNPAR)
+ port->ignore_status_mask |= ASCSTATE_ROE;
+ }
+
+ if ((cflag & CREAD) == 0)
+ port->ignore_status_mask |= UART_DUMMY_UER_RX;
+
+ /* set error signals - framing, parity and overrun, enable receiver */
+ con |= ASCCON_FEN | ASCCON_TOEN | ASCCON_ROEN;
+
+ spin_lock_irqsave(&ltq_asc_lock, flags);
+
+ /* set up CON */
+ ltq_w32_mask(0, con, port->membase + LTQ_ASC_CON);
+
+ /* Set baud rate - take a divider of 2 into account */
+ baud = uart_get_baud_rate(port, new, old, 0, port->uartclk / 16);
+ divisor = uart_get_divisor(port, baud);
+ divisor = divisor / 2 - 1;
+
+ /* disable the baudrate generator */
+ ltq_w32_mask(ASCCON_R, 0, port->membase + LTQ_ASC_CON);
+
+ /* make sure the fractional divider is off */
+ ltq_w32_mask(ASCCON_FDE, 0, port->membase + LTQ_ASC_CON);
+
+ /* set up to use divisor of 2 */
+ ltq_w32_mask(ASCCON_BRS, 0, port->membase + LTQ_ASC_CON);
+
+ /* now we can write the new baudrate into the register */
+ ltq_w32(divisor, port->membase + LTQ_ASC_BG);
+
+ /* turn the baudrate generator back on */
+ ltq_w32_mask(0, ASCCON_R, port->membase + LTQ_ASC_CON);
+
+ /* enable rx */
+ ltq_w32(ASCWHBSTATE_SETREN, port->membase + LTQ_ASC_WHBSTATE);
+
+ spin_unlock_irqrestore(&ltq_asc_lock, flags);
+
+ /* Don't rewrite B0 */
+ if (tty_termios_baud_rate(new))
+ tty_termios_encode_baud_rate(new, baud, baud);
+}
+
+static const char*
+lqasc_type(struct uart_port *port)
+{
+ if (port->type == PORT_LTQ_ASC)
+ return DRVNAME;
+ else
+ return NULL;
+}
+
+static void
+lqasc_release_port(struct uart_port *port)
+{
+ if (port->flags & UPF_IOREMAP) {
+ iounmap(port->membase);
+ port->membase = NULL;
+ }
+}
+
+static int
+lqasc_request_port(struct uart_port *port)
+{
+ struct platform_device *pdev = to_platform_device(port->dev);
+ struct resource *res;
+ int size;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "cannot obtain I/O memory region");
+ return -ENODEV;
+ }
+ size = resource_size(res);
+
+ res = devm_request_mem_region(&pdev->dev, res->start,
+ size, dev_name(&pdev->dev));
+ if (!res) {
+ dev_err(&pdev->dev, "cannot request I/O memory region");
+ return -EBUSY;
+ }
+
+ if (port->flags & UPF_IOREMAP) {
+ port->membase = devm_ioremap_nocache(&pdev->dev,
+ port->mapbase, size);
+ if (port->membase == NULL)
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static void
+lqasc_config_port(struct uart_port *port, int flags)
+{
+ if (flags & UART_CONFIG_TYPE) {
+ port->type = PORT_LTQ_ASC;
+ lqasc_request_port(port);
+ }
+}
+
+static int
+lqasc_verify_port(struct uart_port *port,
+ struct serial_struct *ser)
+{
+ int ret = 0;
+ if (ser->type != PORT_UNKNOWN && ser->type != PORT_LTQ_ASC)
+ ret = -EINVAL;
+ if (ser->irq < 0 || ser->irq >= NR_IRQS)
+ ret = -EINVAL;
+ if (ser->baud_base < 9600)
+ ret = -EINVAL;
+ return ret;
+}
+
+static struct uart_ops lqasc_pops = {
+ .tx_empty = lqasc_tx_empty,
+ .set_mctrl = lqasc_set_mctrl,
+ .get_mctrl = lqasc_get_mctrl,
+ .stop_tx = lqasc_stop_tx,
+ .start_tx = lqasc_start_tx,
+ .stop_rx = lqasc_stop_rx,
+ .enable_ms = lqasc_enable_ms,
+ .break_ctl = lqasc_break_ctl,
+ .startup = lqasc_startup,
+ .shutdown = lqasc_shutdown,
+ .set_termios = lqasc_set_termios,
+ .type = lqasc_type,
+ .release_port = lqasc_release_port,
+ .request_port = lqasc_request_port,
+ .config_port = lqasc_config_port,
+ .verify_port = lqasc_verify_port,
+};
+
+static void
+lqasc_console_putchar(struct uart_port *port, int ch)
+{
+ int fifofree;
+
+ if (!port->membase)
+ return;
+
+ do {
+ fifofree = (ltq_r32(port->membase + LTQ_ASC_FSTAT)
+ & ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF;
+ } while (fifofree == 0);
+ ltq_w8(ch, port->membase + LTQ_ASC_TBUF);
+}
+
+
+static void
+lqasc_console_write(struct console *co, const char *s, u_int count)
+{
+ struct ltq_uart_port *ltq_port;
+ struct uart_port *port;
+ unsigned long flags;
+
+ if (co->index >= MAXPORTS)
+ return;
+
+ ltq_port = lqasc_port[co->index];
+ if (!ltq_port)
+ return;
+
+ port = &ltq_port->port;
+
+ spin_lock_irqsave(&ltq_asc_lock, flags);
+ uart_console_write(port, s, count, lqasc_console_putchar);
+ spin_unlock_irqrestore(&ltq_asc_lock, flags);
+}
+
+static int __init
+lqasc_console_setup(struct console *co, char *options)
+{
+ struct ltq_uart_port *ltq_port;
+ struct uart_port *port;
+ int baud = 115200;
+ int bits = 8;
+ int parity = 'n';
+ int flow = 'n';
+
+ if (co->index >= MAXPORTS)
+ return -ENODEV;
+
+ ltq_port = lqasc_port[co->index];
+ if (!ltq_port)
+ return -ENODEV;
+
+ port = &ltq_port->port;
+
+ port->uartclk = clk_get_rate(ltq_port->clk);
+
+ if (options)
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
+ return uart_set_options(port, co, baud, parity, bits, flow);
+}
+
+static struct console lqasc_console = {
+ .name = "ttyLTQ",
+ .write = lqasc_console_write,
+ .device = uart_console_device,
+ .setup = lqasc_console_setup,
+ .flags = CON_PRINTBUFFER,
+ .index = -1,
+ .data = &lqasc_reg,
+};
+
+static int __init
+lqasc_console_init(void)
+{
+ register_console(&lqasc_console);
+ return 0;
+}
+console_initcall(lqasc_console_init);
+
+static struct uart_driver lqasc_reg = {
+ .owner = THIS_MODULE,
+ .driver_name = DRVNAME,
+ .dev_name = "ttyLTQ",
+ .major = 0,
+ .minor = 0,
+ .nr = MAXPORTS,
+ .cons = &lqasc_console,
+};
+
+static int __init
+lqasc_probe(struct platform_device *pdev)
+{
+ struct ltq_uart_port *ltq_port;
+ struct uart_port *port;
+ struct resource *mmres, *irqres;
+ int tx_irq, rx_irq, err_irq;
+ struct clk *clk;
+ int ret;
+
+ mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ irqres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+ if (!mmres || !irqres)
+ return -ENODEV;
+
+ if (pdev->id >= MAXPORTS)
+ return -EBUSY;
+
+ if (lqasc_port[pdev->id] != NULL)
+ return -EBUSY;
+
+ clk = clk_get(&pdev->dev, "fpi");
+ if (IS_ERR(clk)) {
+ pr_err("failed to get fpi clk\n");
+ return -ENOENT;
+ }
+
+ tx_irq = platform_get_irq_byname(pdev, "tx");
+ rx_irq = platform_get_irq_byname(pdev, "rx");
+ err_irq = platform_get_irq_byname(pdev, "err");
+ if ((tx_irq < 0) | (rx_irq < 0) | (err_irq < 0))
+ return -ENODEV;
+
+ ltq_port = kzalloc(sizeof(struct ltq_uart_port), GFP_KERNEL);
+ if (!ltq_port)
+ return -ENOMEM;
+
+ port = &ltq_port->port;
+
+ port->iotype = SERIAL_IO_MEM;
+ port->flags = ASYNC_BOOT_AUTOCONF | UPF_IOREMAP;
+ port->ops = &lqasc_pops;
+ port->fifosize = 16;
+ port->type = PORT_LTQ_ASC,
+ port->line = pdev->id;
+ port->dev = &pdev->dev;
+
+ port->irq = tx_irq; /* unused, just to be backward-compatibe */
+ port->mapbase = mmres->start;
+
+ ltq_port->clk = clk;
+
+ ltq_port->tx_irq = tx_irq;
+ ltq_port->rx_irq = rx_irq;
+ ltq_port->err_irq = err_irq;
+
+ lqasc_port[pdev->id] = ltq_port;
+ platform_set_drvdata(pdev, ltq_port);
+
+ ret = uart_add_one_port(&lqasc_reg, port);
+
+ return ret;
+}
+
+static struct platform_driver lqasc_driver = {
+ .driver = {
+ .name = DRVNAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+int __init
+init_lqasc(void)
+{
+ int ret;
+
+ ret = uart_register_driver(&lqasc_reg);
+ if (ret != 0)
+ return ret;
+
+ ret = platform_driver_probe(&lqasc_driver, lqasc_probe);
+ if (ret != 0)
+ uart_unregister_driver(&lqasc_reg);
+
+ return ret;
+}
+
+module_init(init_lqasc);
+
+MODULE_DESCRIPTION("Lantiq serial port driver");
+MODULE_LICENSE("GPL");
--- a/drivers/tty/serial/Kconfig
+++ b/drivers/tty/serial/Kconfig
@@ -1391,6 +1391,14 @@ config SERIAL_OF_PLATFORM_NWPSERIAL_CONS
help
Support for Console on the NWP serial ports.
+config SERIAL_LANTIQ
+ bool "Lantiq serial driver"
+ depends on LANTIQ
+ select SERIAL_CORE
+ select SERIAL_CORE_CONSOLE
+ help
+ Support for console and UART on Lantiq SoCs.
+
config SERIAL_QE
tristate "Freescale QUICC Engine serial port support"
depends on QUICC_ENGINE
--- a/drivers/tty/serial/Makefile
+++ b/drivers/tty/serial/Makefile
@@ -94,3 +94,4 @@ obj-$(CONFIG_SERIAL_IFX6X60) += ifx6x6
obj-$(CONFIG_SERIAL_PCH_UART) += pch_uart.o
obj-$(CONFIG_SERIAL_MSM_SMD) += msm_smd_tty.o
obj-$(CONFIG_SERIAL_MXS_AUART) += mxs-auart.o
+obj-$(CONFIG_SERIAL_LANTIQ) += lantiq.o

View File

@ -1,372 +0,0 @@
From bd620ec1ca053bab8ce2562968700e6f80e4ff83 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Fri, 6 May 2011 00:10:00 +0200
Subject: [PATCH 10/13] MIPS: Lantiq: Add DMA support
This patch adds support for the DMA engine found inside the XWAY family of
SoCs. The engine has 5 ports and 20 channels.
Signed-off-by: John Crispin <blogic@openwrt.org>
Signed-off-by: Ralph Hempel <ralph.hempel@lantiq.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/2355/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
.../mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 3 +-
arch/mips/include/asm/mach-lantiq/xway/xway_dma.h | 60 +++++
arch/mips/lantiq/xway/Makefile | 2 +-
arch/mips/lantiq/xway/devices.h | 1 +
arch/mips/lantiq/xway/dma.c | 253 ++++++++++++++++++++
5 files changed, 317 insertions(+), 2 deletions(-)
create mode 100644 arch/mips/include/asm/mach-lantiq/xway/xway_dma.h
create mode 100644 arch/mips/lantiq/xway/dma.c
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
@@ -86,7 +86,8 @@
#define LTQ_PPE32_SIZE 0x40000
/* DMA */
-#define LTQ_DMA_BASE_ADDR 0xBE104100
+#define LTQ_DMA_BASE_ADDR 0x1E104100
+#define LTQ_DMA_SIZE 0x800
/* PCI */
#define PCI_CR_BASE_ADDR 0x1E105400
--- /dev/null
+++ b/arch/mips/include/asm/mach-lantiq/xway/xway_dma.h
@@ -0,0 +1,60 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ */
+
+#ifndef LTQ_DMA_H__
+#define LTQ_DMA_H__
+
+#define LTQ_DESC_SIZE 0x08 /* each descriptor is 64bit */
+#define LTQ_DESC_NUM 0x40 /* 64 descriptors / channel */
+
+#define LTQ_DMA_OWN BIT(31) /* owner bit */
+#define LTQ_DMA_C BIT(30) /* complete bit */
+#define LTQ_DMA_SOP BIT(29) /* start of packet */
+#define LTQ_DMA_EOP BIT(28) /* end of packet */
+#define LTQ_DMA_TX_OFFSET(x) ((x & 0x1f) << 23) /* data bytes offset */
+#define LTQ_DMA_RX_OFFSET(x) ((x & 0x7) << 23) /* data bytes offset */
+#define LTQ_DMA_SIZE_MASK (0xffff) /* the size field is 16 bit */
+
+struct ltq_dma_desc {
+ u32 ctl;
+ u32 addr;
+};
+
+struct ltq_dma_channel {
+ int nr; /* the channel number */
+ int irq; /* the mapped irq */
+ int desc; /* the current descriptor */
+ struct ltq_dma_desc *desc_base; /* the descriptor base */
+ int phys; /* physical addr */
+};
+
+enum {
+ DMA_PORT_ETOP = 0,
+ DMA_PORT_DEU,
+};
+
+extern void ltq_dma_enable_irq(struct ltq_dma_channel *ch);
+extern void ltq_dma_disable_irq(struct ltq_dma_channel *ch);
+extern void ltq_dma_ack_irq(struct ltq_dma_channel *ch);
+extern void ltq_dma_open(struct ltq_dma_channel *ch);
+extern void ltq_dma_close(struct ltq_dma_channel *ch);
+extern void ltq_dma_alloc_tx(struct ltq_dma_channel *ch);
+extern void ltq_dma_alloc_rx(struct ltq_dma_channel *ch);
+extern void ltq_dma_free(struct ltq_dma_channel *ch);
+extern void ltq_dma_init_port(int p);
+
+#endif
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -1,4 +1,4 @@
-obj-y := pmu.o ebu.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o
+obj-y := pmu.o ebu.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o
obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o setup-xway.o
obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o setup-ase.o
--- a/arch/mips/lantiq/xway/devices.h
+++ b/arch/mips/lantiq/xway/devices.h
@@ -10,6 +10,7 @@
#define _LTQ_DEVICES_XWAY_H__
#include "../devices.h"
+#include <linux/phy.h>
extern void ltq_register_gpio(void);
extern void ltq_register_gpio_stp(void);
--- /dev/null
+++ b/arch/mips/lantiq/xway/dma.c
@@ -0,0 +1,253 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+
+#include <lantiq_soc.h>
+#include <xway_dma.h>
+
+#define LTQ_DMA_CTRL 0x10
+#define LTQ_DMA_CPOLL 0x14
+#define LTQ_DMA_CS 0x18
+#define LTQ_DMA_CCTRL 0x1C
+#define LTQ_DMA_CDBA 0x20
+#define LTQ_DMA_CDLEN 0x24
+#define LTQ_DMA_CIS 0x28
+#define LTQ_DMA_CIE 0x2C
+#define LTQ_DMA_PS 0x40
+#define LTQ_DMA_PCTRL 0x44
+#define LTQ_DMA_IRNEN 0xf4
+
+#define DMA_DESCPT BIT(3) /* descriptor complete irq */
+#define DMA_TX BIT(8) /* TX channel direction */
+#define DMA_CHAN_ON BIT(0) /* channel on / off bit */
+#define DMA_PDEN BIT(6) /* enable packet drop */
+#define DMA_CHAN_RST BIT(1) /* channel on / off bit */
+#define DMA_RESET BIT(0) /* channel on / off bit */
+#define DMA_IRQ_ACK 0x7e /* IRQ status register */
+#define DMA_POLL BIT(31) /* turn on channel polling */
+#define DMA_CLK_DIV4 BIT(6) /* polling clock divider */
+#define DMA_2W_BURST BIT(1) /* 2 word burst length */
+#define DMA_MAX_CHANNEL 20 /* the soc has 20 channels */
+#define DMA_ETOP_ENDIANESS (0xf << 8) /* endianess swap etop channels */
+#define DMA_WEIGHT (BIT(17) | BIT(16)) /* default channel wheight */
+
+#define ltq_dma_r32(x) ltq_r32(ltq_dma_membase + (x))
+#define ltq_dma_w32(x, y) ltq_w32(x, ltq_dma_membase + (y))
+#define ltq_dma_w32_mask(x, y, z) ltq_w32_mask(x, y, \
+ ltq_dma_membase + (z))
+
+static struct resource ltq_dma_resource = {
+ .name = "dma",
+ .start = LTQ_DMA_BASE_ADDR,
+ .end = LTQ_DMA_BASE_ADDR + LTQ_DMA_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static void __iomem *ltq_dma_membase;
+
+void
+ltq_dma_enable_irq(struct ltq_dma_channel *ch)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ ltq_dma_w32(ch->nr, LTQ_DMA_CS);
+ ltq_dma_w32_mask(0, 1 << ch->nr, LTQ_DMA_IRNEN);
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL_GPL(ltq_dma_enable_irq);
+
+void
+ltq_dma_disable_irq(struct ltq_dma_channel *ch)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ ltq_dma_w32(ch->nr, LTQ_DMA_CS);
+ ltq_dma_w32_mask(1 << ch->nr, 0, LTQ_DMA_IRNEN);
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL_GPL(ltq_dma_disable_irq);
+
+void
+ltq_dma_ack_irq(struct ltq_dma_channel *ch)
+{
+ unsigned long flags;
+
+ local_irq_save(flags);
+ ltq_dma_w32(ch->nr, LTQ_DMA_CS);
+ ltq_dma_w32(DMA_IRQ_ACK, LTQ_DMA_CIS);
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL_GPL(ltq_dma_ack_irq);
+
+void
+ltq_dma_open(struct ltq_dma_channel *ch)
+{
+ unsigned long flag;
+
+ local_irq_save(flag);
+ ltq_dma_w32(ch->nr, LTQ_DMA_CS);
+ ltq_dma_w32_mask(0, DMA_CHAN_ON, LTQ_DMA_CCTRL);
+ ltq_dma_enable_irq(ch);
+ local_irq_restore(flag);
+}
+EXPORT_SYMBOL_GPL(ltq_dma_open);
+
+void
+ltq_dma_close(struct ltq_dma_channel *ch)
+{
+ unsigned long flag;
+
+ local_irq_save(flag);
+ ltq_dma_w32(ch->nr, LTQ_DMA_CS);
+ ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL);
+ ltq_dma_disable_irq(ch);
+ local_irq_restore(flag);
+}
+EXPORT_SYMBOL_GPL(ltq_dma_close);
+
+static void
+ltq_dma_alloc(struct ltq_dma_channel *ch)
+{
+ unsigned long flags;
+
+ ch->desc = 0;
+ ch->desc_base = dma_alloc_coherent(NULL,
+ LTQ_DESC_NUM * LTQ_DESC_SIZE,
+ &ch->phys, GFP_ATOMIC);
+ memset(ch->desc_base, 0, LTQ_DESC_NUM * LTQ_DESC_SIZE);
+
+ local_irq_save(flags);
+ ltq_dma_w32(ch->nr, LTQ_DMA_CS);
+ ltq_dma_w32(ch->phys, LTQ_DMA_CDBA);
+ ltq_dma_w32(LTQ_DESC_NUM, LTQ_DMA_CDLEN);
+ ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL);
+ wmb();
+ ltq_dma_w32_mask(0, DMA_CHAN_RST, LTQ_DMA_CCTRL);
+ while (ltq_dma_r32(LTQ_DMA_CCTRL) & DMA_CHAN_RST)
+ ;
+ local_irq_restore(flags);
+}
+
+void
+ltq_dma_alloc_tx(struct ltq_dma_channel *ch)
+{
+ unsigned long flags;
+
+ ltq_dma_alloc(ch);
+
+ local_irq_save(flags);
+ ltq_dma_w32(DMA_DESCPT, LTQ_DMA_CIE);
+ ltq_dma_w32_mask(0, 1 << ch->nr, LTQ_DMA_IRNEN);
+ ltq_dma_w32(DMA_WEIGHT | DMA_TX, LTQ_DMA_CCTRL);
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL_GPL(ltq_dma_alloc_tx);
+
+void
+ltq_dma_alloc_rx(struct ltq_dma_channel *ch)
+{
+ unsigned long flags;
+
+ ltq_dma_alloc(ch);
+
+ local_irq_save(flags);
+ ltq_dma_w32(DMA_DESCPT, LTQ_DMA_CIE);
+ ltq_dma_w32_mask(0, 1 << ch->nr, LTQ_DMA_IRNEN);
+ ltq_dma_w32(DMA_WEIGHT, LTQ_DMA_CCTRL);
+ local_irq_restore(flags);
+}
+EXPORT_SYMBOL_GPL(ltq_dma_alloc_rx);
+
+void
+ltq_dma_free(struct ltq_dma_channel *ch)
+{
+ if (!ch->desc_base)
+ return;
+ ltq_dma_close(ch);
+ dma_free_coherent(NULL, LTQ_DESC_NUM * LTQ_DESC_SIZE,
+ ch->desc_base, ch->phys);
+}
+EXPORT_SYMBOL_GPL(ltq_dma_free);
+
+void
+ltq_dma_init_port(int p)
+{
+ ltq_dma_w32(p, LTQ_DMA_PS);
+ switch (p) {
+ case DMA_PORT_ETOP:
+ /*
+ * Tell the DMA engine to swap the endianess of data frames and
+ * drop packets if the channel arbitration fails.
+ */
+ ltq_dma_w32_mask(0, DMA_ETOP_ENDIANESS | DMA_PDEN,
+ LTQ_DMA_PCTRL);
+ break;
+
+ case DMA_PORT_DEU:
+ ltq_dma_w32((DMA_2W_BURST << 4) | (DMA_2W_BURST << 2),
+ LTQ_DMA_PCTRL);
+ break;
+
+ default:
+ break;
+ }
+}
+EXPORT_SYMBOL_GPL(ltq_dma_init_port);
+
+int __init
+ltq_dma_init(void)
+{
+ int i;
+
+ /* insert and request the memory region */
+ if (insert_resource(&iomem_resource, &ltq_dma_resource) < 0)
+ panic("Failed to insert dma memory\n");
+
+ if (request_mem_region(ltq_dma_resource.start,
+ resource_size(&ltq_dma_resource), "dma") < 0)
+ panic("Failed to request dma memory\n");
+
+ /* remap dma register range */
+ ltq_dma_membase = ioremap_nocache(ltq_dma_resource.start,
+ resource_size(&ltq_dma_resource));
+ if (!ltq_dma_membase)
+ panic("Failed to remap dma memory\n");
+
+ /* power up and reset the dma engine */
+ ltq_pmu_enable(PMU_DMA);
+ ltq_dma_w32_mask(0, DMA_RESET, LTQ_DMA_CTRL);
+
+ /* disable all interrupts */
+ ltq_dma_w32(0, LTQ_DMA_IRNEN);
+
+ /* reset/configure each channel */
+ for (i = 0; i < DMA_MAX_CHANNEL; i++) {
+ ltq_dma_w32(i, LTQ_DMA_CS);
+ ltq_dma_w32(DMA_CHAN_RST, LTQ_DMA_CCTRL);
+ ltq_dma_w32(DMA_POLL | DMA_CLK_DIV4, LTQ_DMA_CPOLL);
+ ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL);
+ }
+ return 0;
+}
+
+postcore_initcall(ltq_dma_init);

View File

@ -1,942 +0,0 @@
From 435de86088af82496bcba69165cd7422bb4622ec Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Fri, 6 May 2011 00:10:01 +0200
Subject: [PATCH 11/13] MIPS: Lantiq: Add ethernet driver
This patch adds the driver for the ETOP Packet Processing Engine (PPE32)
found inside the XWAY family of Lantiq MIPS SoCs. This driver makes 100MBit
ethernet work. Support for all 8 dma channels, gbit and the embedded switch
found on the ar9/vr9 still needs to be implemented.
Signed-off-by: John Crispin <blogic@openwrt.org>
Signed-off-by: Ralph Hempel <ralph.hempel@lantiq.com>
Cc: linux-mips@linux-mips.org
Cc: netdev@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/2357/
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
.../mips/include/asm/mach-lantiq/lantiq_platform.h | 7 +
.../mips/include/asm/mach-lantiq/xway/lantiq_soc.h | 4 +-
arch/mips/lantiq/xway/devices.c | 23 +
arch/mips/lantiq/xway/devices.h | 1 +
drivers/net/Kconfig | 7 +
drivers/net/Makefile | 1 +
drivers/net/lantiq_etop.c | 805 ++++++++++++++++++++
7 files changed, 846 insertions(+), 2 deletions(-)
create mode 100644 drivers/net/lantiq_etop.c
--- a/arch/mips/include/asm/mach-lantiq/lantiq_platform.h
+++ b/arch/mips/include/asm/mach-lantiq/lantiq_platform.h
@@ -10,6 +10,7 @@
#define _LANTIQ_PLATFORM_H__
#include <linux/mtd/partitions.h>
+#include <linux/socket.h>
/* struct used to pass info to the pci core */
enum {
@@ -43,4 +44,10 @@ struct ltq_pci_data {
int irq[16];
};
+/* struct used to pass info to network drivers */
+struct ltq_eth_data {
+ struct sockaddr mac;
+ int mii_mode;
+};
+
#endif
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
@@ -82,8 +82,8 @@
#define PMU_SWITCH 0x10000000
/* ETOP - ethernet */
-#define LTQ_PPE32_BASE_ADDR 0xBE180000
-#define LTQ_PPE32_SIZE 0x40000
+#define LTQ_ETOP_BASE_ADDR 0x1E180000
+#define LTQ_ETOP_SIZE 0x40000
/* DMA */
#define LTQ_DMA_BASE_ADDR 0x1E104100
--- a/arch/mips/lantiq/xway/devices.c
+++ b/arch/mips/lantiq/xway/devices.c
@@ -96,3 +96,26 @@ void __init ltq_register_ase_asc(void)
platform_device_register_simple("ltq_asc", 0,
ltq_ase_asc_resources, ARRAY_SIZE(ltq_ase_asc_resources));
}
+
+/* ethernet */
+static struct resource ltq_etop_resources = {
+ .name = "etop",
+ .start = LTQ_ETOP_BASE_ADDR,
+ .end = LTQ_ETOP_BASE_ADDR + LTQ_ETOP_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device ltq_etop = {
+ .name = "ltq_etop",
+ .resource = &ltq_etop_resources,
+ .num_resources = 1,
+};
+
+void __init
+ltq_register_etop(struct ltq_eth_data *eth)
+{
+ if (eth) {
+ ltq_etop.dev.platform_data = eth;
+ platform_device_register(&ltq_etop);
+ }
+}
--- a/arch/mips/lantiq/xway/devices.h
+++ b/arch/mips/lantiq/xway/devices.h
@@ -15,5 +15,6 @@
extern void ltq_register_gpio(void);
extern void ltq_register_gpio_stp(void);
extern void ltq_register_ase_asc(void);
+extern void ltq_register_etop(struct ltq_eth_data *eth);
#endif
--- a/drivers/net/Kconfig
+++ b/drivers/net/Kconfig
@@ -2017,6 +2017,13 @@ config FTMAC100
from Faraday. It is used on Faraday A320, Andes AG101 and some
other ARM/NDS32 SoC's.
+config LANTIQ_ETOP
+ tristate "Lantiq SoC ETOP driver"
+ depends on SOC_TYPE_XWAY
+ help
+ Support for the MII0 inside the Lantiq SoC
+
+
source "drivers/net/fs_enet/Kconfig"
source "drivers/net/octeon/Kconfig"
--- a/drivers/net/Makefile
+++ b/drivers/net/Makefile
@@ -259,6 +259,7 @@ obj-$(CONFIG_MLX4_CORE) += mlx4/
obj-$(CONFIG_ENC28J60) += enc28j60.o
obj-$(CONFIG_ETHOC) += ethoc.o
obj-$(CONFIG_GRETH) += greth.o
+obj-$(CONFIG_LANTIQ_ETOP) += lantiq_etop.o
obj-$(CONFIG_XTENSA_XT2000_SONIC) += xtsonic.o
--- /dev/null
+++ b/drivers/net/lantiq_etop.c
@@ -0,0 +1,813 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2011 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include <linux/uaccess.h>
+#include <linux/in.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/phy.h>
+#include <linux/ip.h>
+#include <linux/tcp.h>
+#include <linux/skbuff.h>
+#include <linux/mm.h>
+#include <linux/platform_device.h>
+#include <linux/ethtool.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include <asm/checksum.h>
+
+#include <lantiq_soc.h>
+#include <xway_dma.h>
+#include <lantiq_platform.h>
+
+#define LTQ_ETOP_MDIO 0x11804
+#define MDIO_REQUEST 0x80000000
+#define MDIO_READ 0x40000000
+#define MDIO_ADDR_MASK 0x1f
+#define MDIO_ADDR_OFFSET 0x15
+#define MDIO_REG_MASK 0x1f
+#define MDIO_REG_OFFSET 0x10
+#define MDIO_VAL_MASK 0xffff
+
+#define PPE32_CGEN 0x800
+#define LTQ_PPE32_ENET_MAC_CFG 0x1840
+
+#define LTQ_ETOP_ENETS0 0x11850
+#define LTQ_ETOP_MAC_DA0 0x1186C
+#define LTQ_ETOP_MAC_DA1 0x11870
+#define LTQ_ETOP_CFG 0x16020
+#define LTQ_ETOP_IGPLEN 0x16080
+
+#define MAX_DMA_CHAN 0x8
+#define MAX_DMA_CRC_LEN 0x4
+#define MAX_DMA_DATA_LEN 0x600
+
+#define ETOP_FTCU BIT(28)
+#define ETOP_MII_MASK 0xf
+#define ETOP_MII_NORMAL 0xd
+#define ETOP_MII_REVERSE 0xe
+#define ETOP_PLEN_UNDER 0x40
+#define ETOP_CGEN 0x800
+
+/* use 2 static channels for TX/RX */
+#define LTQ_ETOP_TX_CHANNEL 1
+#define LTQ_ETOP_RX_CHANNEL 6
+#define IS_TX(x) (x == LTQ_ETOP_TX_CHANNEL)
+#define IS_RX(x) (x == LTQ_ETOP_RX_CHANNEL)
+
+#define ltq_etop_r32(x) ltq_r32(ltq_etop_membase + (x))
+#define ltq_etop_w32(x, y) ltq_w32(x, ltq_etop_membase + (y))
+#define ltq_etop_w32_mask(x, y, z) \
+ ltq_w32_mask(x, y, ltq_etop_membase + (z))
+
+#define DRV_VERSION "1.0"
+
+#ifndef netdev_err
+#define netdev_err(a, b, ...) printk(b, ##__VA_ARGS__)
+#endif
+
+#ifndef pr_warn
+#define pr_warn pr_warning
+#endif
+
+static void __iomem *ltq_etop_membase;
+
+struct ltq_etop_chan {
+ int idx;
+ int tx_free;
+ struct net_device *netdev;
+ struct napi_struct napi;
+ struct ltq_dma_channel dma;
+ struct sk_buff *skb[LTQ_DESC_NUM];
+};
+
+struct ltq_etop_priv {
+ struct net_device *netdev;
+ struct ltq_eth_data *pldata;
+ struct resource *res;
+
+ struct mii_bus *mii_bus;
+ struct phy_device *phydev;
+
+ struct ltq_etop_chan ch[MAX_DMA_CHAN];
+ int tx_free[MAX_DMA_CHAN >> 1];
+
+ spinlock_t lock;
+};
+
+static int
+ltq_etop_alloc_skb(struct ltq_etop_chan *ch)
+{
+ ch->skb[ch->dma.desc] = dev_alloc_skb(MAX_DMA_DATA_LEN);
+ if (!ch->skb[ch->dma.desc])
+ return -ENOMEM;
+ ch->dma.desc_base[ch->dma.desc].addr = dma_map_single(NULL,
+ ch->skb[ch->dma.desc]->data, MAX_DMA_DATA_LEN,
+ DMA_FROM_DEVICE);
+ ch->dma.desc_base[ch->dma.desc].addr =
+ CPHYSADDR(ch->skb[ch->dma.desc]->data);
+ ch->dma.desc_base[ch->dma.desc].ctl =
+ LTQ_DMA_OWN | LTQ_DMA_RX_OFFSET(NET_IP_ALIGN) |
+ MAX_DMA_DATA_LEN;
+ skb_reserve(ch->skb[ch->dma.desc], NET_IP_ALIGN);
+ return 0;
+}
+
+static void
+ltq_etop_hw_receive(struct ltq_etop_chan *ch)
+{
+ struct ltq_etop_priv *priv = netdev_priv(ch->netdev);
+ struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
+ struct sk_buff *skb = ch->skb[ch->dma.desc];
+ int len = (desc->ctl & LTQ_DMA_SIZE_MASK) - MAX_DMA_CRC_LEN;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ if (ltq_etop_alloc_skb(ch)) {
+ netdev_err(ch->netdev,
+ "failed to allocate new rx buffer, stopping DMA\n");
+ ltq_dma_close(&ch->dma);
+ }
+ ch->dma.desc++;
+ ch->dma.desc %= LTQ_DESC_NUM;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ skb_put(skb, len);
+ skb->dev = ch->netdev;
+ skb->protocol = eth_type_trans(skb, ch->netdev);
+ netif_receive_skb(skb);
+}
+
+static int
+ltq_etop_poll_rx(struct napi_struct *napi, int budget)
+{
+ struct ltq_etop_chan *ch = container_of(napi,
+ struct ltq_etop_chan, napi);
+ int rx = 0;
+ int complete = 0;
+
+ while ((rx < budget) && !complete) {
+ struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
+
+ if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) == LTQ_DMA_C) {
+ ltq_etop_hw_receive(ch);
+ rx++;
+ } else {
+ complete = 1;
+ }
+ }
+ if (complete || !rx) {
+ napi_complete(&ch->napi);
+ ltq_dma_ack_irq(&ch->dma);
+ }
+ return rx;
+}
+
+static int
+ltq_etop_poll_tx(struct napi_struct *napi, int budget)
+{
+ struct ltq_etop_chan *ch =
+ container_of(napi, struct ltq_etop_chan, napi);
+ struct ltq_etop_priv *priv = netdev_priv(ch->netdev);
+ struct netdev_queue *txq =
+ netdev_get_tx_queue(ch->netdev, ch->idx >> 1);
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ while ((ch->dma.desc_base[ch->tx_free].ctl &
+ (LTQ_DMA_OWN | LTQ_DMA_C)) == LTQ_DMA_C) {
+ dev_kfree_skb_any(ch->skb[ch->tx_free]);
+ ch->skb[ch->tx_free] = NULL;
+ memset(&ch->dma.desc_base[ch->tx_free], 0,
+ sizeof(struct ltq_dma_desc));
+ ch->tx_free++;
+ ch->tx_free %= LTQ_DESC_NUM;
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ if (netif_tx_queue_stopped(txq))
+ netif_tx_start_queue(txq);
+ napi_complete(&ch->napi);
+ ltq_dma_ack_irq(&ch->dma);
+ return 1;
+}
+
+static irqreturn_t
+ltq_etop_dma_irq(int irq, void *_priv)
+{
+ struct ltq_etop_priv *priv = _priv;
+ int ch = irq - LTQ_DMA_CH0_INT;
+
+ napi_schedule(&priv->ch[ch].napi);
+ return IRQ_HANDLED;
+}
+
+static void
+ltq_etop_free_channel(struct net_device *dev, struct ltq_etop_chan *ch)
+{
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+
+ ltq_dma_free(&ch->dma);
+ if (ch->dma.irq)
+ free_irq(ch->dma.irq, priv);
+ if (IS_RX(ch->idx)) {
+ int desc;
+ for (desc = 0; desc < LTQ_DESC_NUM; desc++)
+ dev_kfree_skb_any(ch->skb[ch->dma.desc]);
+ }
+}
+
+static void
+ltq_etop_hw_exit(struct net_device *dev)
+{
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+ int i;
+
+ ltq_pmu_disable(PMU_PPE);
+ for (i = 0; i < MAX_DMA_CHAN; i++)
+ if (IS_TX(i) || IS_RX(i))
+ ltq_etop_free_channel(dev, &priv->ch[i]);
+}
+
+static int
+ltq_etop_hw_init(struct net_device *dev)
+{
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+ int i;
+
+ ltq_pmu_enable(PMU_PPE);
+
+ switch (priv->pldata->mii_mode) {
+ case PHY_INTERFACE_MODE_RMII:
+ ltq_etop_w32_mask(ETOP_MII_MASK,
+ ETOP_MII_REVERSE, LTQ_ETOP_CFG);
+ break;
+
+ case PHY_INTERFACE_MODE_MII:
+ ltq_etop_w32_mask(ETOP_MII_MASK,
+ ETOP_MII_NORMAL, LTQ_ETOP_CFG);
+ break;
+
+ default:
+ netdev_err(dev, "unknown mii mode %d\n",
+ priv->pldata->mii_mode);
+ return -ENOTSUPP;
+ }
+
+ /* enable crc generation */
+ ltq_etop_w32(PPE32_CGEN, LTQ_PPE32_ENET_MAC_CFG);
+
+ ltq_dma_init_port(DMA_PORT_ETOP);
+
+ for (i = 0; i < MAX_DMA_CHAN; i++) {
+ int irq = LTQ_DMA_CH0_INT + i;
+ struct ltq_etop_chan *ch = &priv->ch[i];
+
+ ch->idx = ch->dma.nr = i;
+
+ if (IS_TX(i)) {
+ ltq_dma_alloc_tx(&ch->dma);
+ request_irq(irq, ltq_etop_dma_irq, IRQF_DISABLED,
+ "etop_tx", priv);
+ } else if (IS_RX(i)) {
+ ltq_dma_alloc_rx(&ch->dma);
+ for (ch->dma.desc = 0; ch->dma.desc < LTQ_DESC_NUM;
+ ch->dma.desc++)
+ if (ltq_etop_alloc_skb(ch))
+ return -ENOMEM;
+ ch->dma.desc = 0;
+ request_irq(irq, ltq_etop_dma_irq, IRQF_DISABLED,
+ "etop_rx", priv);
+ }
+ ch->dma.irq = irq;
+ }
+ return 0;
+}
+
+static void
+ltq_etop_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+{
+ strcpy(info->driver, "Lantiq ETOP");
+ strcpy(info->bus_info, "internal");
+ strcpy(info->version, DRV_VERSION);
+}
+
+static int
+ltq_etop_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+
+ return phy_ethtool_gset(priv->phydev, cmd);
+}
+
+static int
+ltq_etop_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
+{
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+
+ return phy_ethtool_sset(priv->phydev, cmd);
+}
+
+static int
+ltq_etop_nway_reset(struct net_device *dev)
+{
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+
+ return phy_start_aneg(priv->phydev);
+}
+
+static const struct ethtool_ops ltq_etop_ethtool_ops = {
+ .get_drvinfo = ltq_etop_get_drvinfo,
+ .get_settings = ltq_etop_get_settings,
+ .set_settings = ltq_etop_set_settings,
+ .nway_reset = ltq_etop_nway_reset,
+};
+
+static int
+ltq_etop_mdio_wr(struct mii_bus *bus, int phy_addr, int phy_reg, u16 phy_data)
+{
+ u32 val = MDIO_REQUEST |
+ ((phy_addr & MDIO_ADDR_MASK) << MDIO_ADDR_OFFSET) |
+ ((phy_reg & MDIO_REG_MASK) << MDIO_REG_OFFSET) |
+ phy_data;
+
+ while (ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_REQUEST)
+ ;
+ ltq_etop_w32(val, LTQ_ETOP_MDIO);
+ return 0;
+}
+
+static int
+ltq_etop_mdio_rd(struct mii_bus *bus, int phy_addr, int phy_reg)
+{
+ u32 val = MDIO_REQUEST | MDIO_READ |
+ ((phy_addr & MDIO_ADDR_MASK) << MDIO_ADDR_OFFSET) |
+ ((phy_reg & MDIO_REG_MASK) << MDIO_REG_OFFSET);
+
+ while (ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_REQUEST)
+ ;
+ ltq_etop_w32(val, LTQ_ETOP_MDIO);
+ while (ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_REQUEST)
+ ;
+ val = ltq_etop_r32(LTQ_ETOP_MDIO) & MDIO_VAL_MASK;
+ return val;
+}
+
+static void
+ltq_etop_mdio_link(struct net_device *dev)
+{
+ /* nothing to do */
+}
+
+static int
+ltq_etop_mdio_probe(struct net_device *dev)
+{
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+ struct phy_device *phydev = NULL;
+ int phy_addr;
+
+ for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
+ if (priv->mii_bus->phy_map[phy_addr]) {
+ phydev = priv->mii_bus->phy_map[phy_addr];
+ break;
+ }
+ }
+
+ if (!phydev) {
+ netdev_err(dev, "no PHY found\n");
+ return -ENODEV;
+ }
+
+ phydev = phy_connect(dev, dev_name(&phydev->dev), &ltq_etop_mdio_link,
+ 0, priv->pldata->mii_mode);
+
+ if (IS_ERR(phydev)) {
+ netdev_err(dev, "Could not attach to PHY\n");
+ return PTR_ERR(phydev);
+ }
+
+ phydev->supported &= (SUPPORTED_10baseT_Half
+ | SUPPORTED_10baseT_Full
+ | SUPPORTED_100baseT_Half
+ | SUPPORTED_100baseT_Full
+ | SUPPORTED_Autoneg
+ | SUPPORTED_MII
+ | SUPPORTED_TP);
+
+ phydev->advertising = phydev->supported;
+ priv->phydev = phydev;
+ pr_info("%s: attached PHY [%s] (phy_addr=%s, irq=%d)\n",
+ dev->name, phydev->drv->name,
+ dev_name(&phydev->dev), phydev->irq);
+
+ return 0;
+}
+
+static int
+ltq_etop_mdio_init(struct net_device *dev)
+{
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+ int i;
+ int err;
+
+ priv->mii_bus = mdiobus_alloc();
+ if (!priv->mii_bus) {
+ netdev_err(dev, "failed to allocate mii bus\n");
+ err = -ENOMEM;
+ goto err_out;
+ }
+
+ priv->mii_bus->priv = dev;
+ priv->mii_bus->read = ltq_etop_mdio_rd;
+ priv->mii_bus->write = ltq_etop_mdio_wr;
+ priv->mii_bus->name = "ltq_mii";
+ snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%x", 0);
+ priv->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
+ if (!priv->mii_bus->irq) {
+ err = -ENOMEM;
+ goto err_out_free_mdiobus;
+ }
+
+ for (i = 0; i < PHY_MAX_ADDR; ++i)
+ priv->mii_bus->irq[i] = PHY_POLL;
+
+ if (mdiobus_register(priv->mii_bus)) {
+ err = -ENXIO;
+ goto err_out_free_mdio_irq;
+ }
+
+ if (ltq_etop_mdio_probe(dev)) {
+ err = -ENXIO;
+ goto err_out_unregister_bus;
+ }
+ return 0;
+
+err_out_unregister_bus:
+ mdiobus_unregister(priv->mii_bus);
+err_out_free_mdio_irq:
+ kfree(priv->mii_bus->irq);
+err_out_free_mdiobus:
+ mdiobus_free(priv->mii_bus);
+err_out:
+ return err;
+}
+
+static void
+ltq_etop_mdio_cleanup(struct net_device *dev)
+{
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+
+ phy_disconnect(priv->phydev);
+ mdiobus_unregister(priv->mii_bus);
+ kfree(priv->mii_bus->irq);
+ mdiobus_free(priv->mii_bus);
+}
+
+static int
+ltq_etop_open(struct net_device *dev)
+{
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+ int i;
+
+ for (i = 0; i < MAX_DMA_CHAN; i++) {
+ struct ltq_etop_chan *ch = &priv->ch[i];
+
+ if (!IS_TX(i) && (!IS_RX(i)))
+ continue;
+ ltq_dma_open(&ch->dma);
+ napi_enable(&ch->napi);
+ }
+ phy_start(priv->phydev);
+ netif_tx_start_all_queues(dev);
+ return 0;
+}
+
+static int
+ltq_etop_stop(struct net_device *dev)
+{
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+ int i;
+
+ netif_tx_stop_all_queues(dev);
+ phy_stop(priv->phydev);
+ for (i = 0; i < MAX_DMA_CHAN; i++) {
+ struct ltq_etop_chan *ch = &priv->ch[i];
+
+ if (!IS_RX(i) && !IS_TX(i))
+ continue;
+ napi_disable(&ch->napi);
+ ltq_dma_close(&ch->dma);
+ }
+ return 0;
+}
+
+static int
+ltq_etop_tx(struct sk_buff *skb, struct net_device *dev)
+{
+ int queue = skb_get_queue_mapping(skb);
+ struct netdev_queue *txq = netdev_get_tx_queue(dev, queue);
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+ struct ltq_etop_chan *ch = &priv->ch[(queue << 1) | 1];
+ struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
+ int len;
+ unsigned long flags;
+ u32 byte_offset;
+
+ len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
+
+ if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) || ch->skb[ch->dma.desc]) {
+ dev_kfree_skb_any(skb);
+ netdev_err(dev, "tx ring full\n");
+ netif_tx_stop_queue(txq);
+ return NETDEV_TX_BUSY;
+ }
+
+ /* dma needs to start on a 16 byte aligned address */
+ byte_offset = CPHYSADDR(skb->data) % 16;
+ ch->skb[ch->dma.desc] = skb;
+
+ dev->trans_start = jiffies;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ desc->addr = ((unsigned int) dma_map_single(NULL, skb->data, len,
+ DMA_TO_DEVICE)) - byte_offset;
+ wmb();
+ desc->ctl = LTQ_DMA_OWN | LTQ_DMA_SOP | LTQ_DMA_EOP |
+ LTQ_DMA_TX_OFFSET(byte_offset) | (len & LTQ_DMA_SIZE_MASK);
+ ch->dma.desc++;
+ ch->dma.desc %= LTQ_DESC_NUM;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ if (ch->dma.desc_base[ch->dma.desc].ctl & LTQ_DMA_OWN)
+ netif_tx_stop_queue(txq);
+
+ return NETDEV_TX_OK;
+}
+
+static int
+ltq_etop_change_mtu(struct net_device *dev, int new_mtu)
+{
+ int ret = eth_change_mtu(dev, new_mtu);
+
+ if (!ret) {
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lock, flags);
+ ltq_etop_w32((ETOP_PLEN_UNDER << 16) | new_mtu,
+ LTQ_ETOP_IGPLEN);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
+ return ret;
+}
+
+static int
+ltq_etop_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+{
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+
+ /* TODO: mii-toll reports "No MII transceiver present!." ?!*/
+ return phy_mii_ioctl(priv->phydev, rq, cmd);
+}
+
+static int
+ltq_etop_set_mac_address(struct net_device *dev, void *p)
+{
+ int ret = eth_mac_addr(dev, p);
+
+ if (!ret) {
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+ unsigned long flags;
+
+ /* store the mac for the unicast filter */
+ spin_lock_irqsave(&priv->lock, flags);
+ ltq_etop_w32(*((u32 *)dev->dev_addr), LTQ_ETOP_MAC_DA0);
+ ltq_etop_w32(*((u16 *)&dev->dev_addr[4]) << 16,
+ LTQ_ETOP_MAC_DA1);
+ spin_unlock_irqrestore(&priv->lock, flags);
+ }
+ return ret;
+}
+
+static void
+ltq_etop_set_multicast_list(struct net_device *dev)
+{
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+ unsigned long flags;
+
+ /* ensure that the unicast filter is not enabled in promiscious mode */
+ spin_lock_irqsave(&priv->lock, flags);
+ if ((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI))
+ ltq_etop_w32_mask(ETOP_FTCU, 0, LTQ_ETOP_ENETS0);
+ else
+ ltq_etop_w32_mask(0, ETOP_FTCU, LTQ_ETOP_ENETS0);
+ spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+static u16
+ltq_etop_select_queue(struct net_device *dev, struct sk_buff *skb)
+{
+ /* we are currently only using the first queue */
+ return 0;
+}
+
+static int
+ltq_etop_init(struct net_device *dev)
+{
+ struct ltq_etop_priv *priv = netdev_priv(dev);
+ struct sockaddr mac;
+ int err;
+
+ ether_setup(dev);
+ dev->watchdog_timeo = 10 * HZ;
+ err = ltq_etop_hw_init(dev);
+ if (err)
+ goto err_hw;
+ ltq_etop_change_mtu(dev, 1500);
+
+ memcpy(&mac, &priv->pldata->mac, sizeof(struct sockaddr));
+ if (!is_valid_ether_addr(mac.sa_data)) {
+ pr_warn("etop: invalid MAC, using random\n");
+ random_ether_addr(mac.sa_data);
+ }
+
+ err = ltq_etop_set_mac_address(dev, &mac);
+ if (err)
+ goto err_netdev;
+ ltq_etop_set_multicast_list(dev);
+ err = ltq_etop_mdio_init(dev);
+ if (err)
+ goto err_netdev;
+ return 0;
+
+err_netdev:
+ unregister_netdev(dev);
+ free_netdev(dev);
+err_hw:
+ ltq_etop_hw_exit(dev);
+ return err;
+}
+
+static void
+ltq_etop_tx_timeout(struct net_device *dev)
+{
+ int err;
+
+ ltq_etop_hw_exit(dev);
+ err = ltq_etop_hw_init(dev);
+ if (err)
+ goto err_hw;
+ dev->trans_start = jiffies;
+ netif_wake_queue(dev);
+ return;
+
+err_hw:
+ ltq_etop_hw_exit(dev);
+ netdev_err(dev, "failed to restart etop after TX timeout\n");
+}
+
+static const struct net_device_ops ltq_eth_netdev_ops = {
+ .ndo_open = ltq_etop_open,
+ .ndo_stop = ltq_etop_stop,
+ .ndo_start_xmit = ltq_etop_tx,
+ .ndo_change_mtu = ltq_etop_change_mtu,
+ .ndo_do_ioctl = ltq_etop_ioctl,
+ .ndo_set_mac_address = ltq_etop_set_mac_address,
+ .ndo_validate_addr = eth_validate_addr,
+ .ndo_set_multicast_list = ltq_etop_set_multicast_list,
+ .ndo_select_queue = ltq_etop_select_queue,
+ .ndo_init = ltq_etop_init,
+ .ndo_tx_timeout = ltq_etop_tx_timeout,
+};
+
+static int __init
+ltq_etop_probe(struct platform_device *pdev)
+{
+ struct net_device *dev;
+ struct ltq_etop_priv *priv;
+ struct resource *res;
+ int err;
+ int i;
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&pdev->dev, "failed to get etop resource\n");
+ err = -ENOENT;
+ goto err_out;
+ }
+
+ res = devm_request_mem_region(&pdev->dev, res->start,
+ resource_size(res), dev_name(&pdev->dev));
+ if (!res) {
+ dev_err(&pdev->dev, "failed to request etop resource\n");
+ err = -EBUSY;
+ goto err_out;
+ }
+
+ ltq_etop_membase = devm_ioremap_nocache(&pdev->dev,
+ res->start, resource_size(res));
+ if (!ltq_etop_membase) {
+ dev_err(&pdev->dev, "failed to remap etop engine %d\n",
+ pdev->id);
+ err = -ENOMEM;
+ goto err_out;
+ }
+
+ dev = alloc_etherdev_mq(sizeof(struct ltq_etop_priv), 4);
+ strcpy(dev->name, "eth%d");
+ dev->netdev_ops = &ltq_eth_netdev_ops;
+ dev->ethtool_ops = &ltq_etop_ethtool_ops;
+ priv = netdev_priv(dev);
+ priv->res = res;
+ priv->pldata = dev_get_platdata(&pdev->dev);
+ priv->netdev = dev;
+ spin_lock_init(&priv->lock);
+
+ for (i = 0; i < MAX_DMA_CHAN; i++) {
+ if (IS_TX(i))
+ netif_napi_add(dev, &priv->ch[i].napi,
+ ltq_etop_poll_tx, 8);
+ else if (IS_RX(i))
+ netif_napi_add(dev, &priv->ch[i].napi,
+ ltq_etop_poll_rx, 32);
+ priv->ch[i].netdev = dev;
+ }
+
+ err = register_netdev(dev);
+ if (err)
+ goto err_free;
+
+ platform_set_drvdata(pdev, dev);
+ return 0;
+
+err_free:
+ kfree(dev);
+err_out:
+ return err;
+}
+
+static int __devexit
+ltq_etop_remove(struct platform_device *pdev)
+{
+ struct net_device *dev = platform_get_drvdata(pdev);
+
+ if (dev) {
+ netif_tx_stop_all_queues(dev);
+ ltq_etop_hw_exit(dev);
+ ltq_etop_mdio_cleanup(dev);
+ unregister_netdev(dev);
+ }
+ return 0;
+}
+
+static struct platform_driver ltq_mii_driver = {
+ .remove = __devexit_p(ltq_etop_remove),
+ .driver = {
+ .name = "ltq_etop",
+ .owner = THIS_MODULE,
+ },
+};
+
+int __init
+init_ltq_etop(void)
+{
+ int ret = platform_driver_probe(&ltq_mii_driver, ltq_etop_probe);
+
+ if (ret)
+ pr_err("ltq_etop: Error registering platfom driver!");
+ return ret;
+}
+
+static void __exit
+exit_ltq_etop(void)
+{
+ platform_driver_unregister(&ltq_mii_driver);
+}
+
+module_init(init_ltq_etop);
+module_exit(exit_ltq_etop);
+
+MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
+MODULE_DESCRIPTION("Lantiq SoC ETOP");
+MODULE_LICENSE("GPL");

View File

@ -1,45 +0,0 @@
From 72a9b536ef81f06bb8042abee0410458f5df93d2 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Fri, 6 May 2011 00:10:02 +0200
Subject: [PATCH 12/13] MIPS: Lantiq: Add etop board support
Register the etop platform device inside the machtype specific init code.
Signed-off-by: John Crispin <blogic@openwrt.org>
Signed-off-by: Ralph Hempel <ralph.hempel@lantiq.com>
Signed-off-by: David Daney <ddaney@caviumnetworks.com>
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/2356/
Patchwork: https://patchwork.linux-mips.org/patch/2370/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
arch/mips/lantiq/xway/mach-easy50712.c | 6 ++++++
1 files changed, 6 insertions(+), 0 deletions(-)
--- a/arch/mips/lantiq/xway/mach-easy50712.c
+++ b/arch/mips/lantiq/xway/mach-easy50712.c
@@ -12,6 +12,7 @@
#include <linux/mtd/partitions.h>
#include <linux/mtd/physmap.h>
#include <linux/input.h>
+#include <linux/phy.h>
#include <lantiq_soc.h>
#include <irq.h>
@@ -55,11 +56,16 @@ static struct ltq_pci_data ltq_pci_data
},
};
+static struct ltq_eth_data ltq_eth_data = {
+ .mii_mode = PHY_INTERFACE_MODE_MII,
+};
+
static void __init easy50712_init(void)
{
ltq_register_gpio_stp();
ltq_register_nor(&easy50712_flash_data);
ltq_register_pci(&ltq_pci_data);
+ ltq_register_etop(&ltq_eth_data);
}
MIPS_MACHINE(LTQ_MACH_EASY50712,

View File

@ -1,310 +0,0 @@
From 3466449c8f455da0cb646231602e6af16190f592 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 5 May 2011 23:00:23 +0200
Subject: [PATCH 13/13] MIPS: Lantiq: Add watchdog support
This patch adds the driver for the watchdog found inside the Lantiq SoC family.
Signed-off-by: John Crispin <blogic@openwrt.org>
Signed-off-by: Ralph Hempel <ralph.hempel@lantiq.com>
Cc: Wim Van Sebroeck <wim@iguana.be>
Cc: linux-mips@linux-mips.org
Cc: linux-watchdog@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/2327/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
---
drivers/watchdog/Kconfig | 6 +
drivers/watchdog/Makefile | 1 +
drivers/watchdog/lantiq_wdt.c | 261 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 268 insertions(+), 0 deletions(-)
create mode 100644 drivers/watchdog/lantiq_wdt.c
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -990,6 +990,12 @@ config BCM63XX_WDT
To compile this driver as a loadable module, choose M here.
The module will be called bcm63xx_wdt.
+config LANTIQ_WDT
+ tristate "Lantiq SoC watchdog"
+ depends on LANTIQ
+ help
+ Hardware driver for the Lantiq SoC Watchdog Timer.
+
# PARISC Architecture
# POWERPC Architecture
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -123,6 +123,7 @@ obj-$(CONFIG_AR7_WDT) += ar7_wdt.o
obj-$(CONFIG_TXX9_WDT) += txx9wdt.o
obj-$(CONFIG_OCTEON_WDT) += octeon-wdt.o
octeon-wdt-y := octeon-wdt-main.o octeon-wdt-nmi.o
+obj-$(CONFIG_LANTIQ_WDT) += lantiq_wdt.o
# PARISC Architecture
--- /dev/null
+++ b/drivers/watchdog/lantiq_wdt.c
@@ -0,0 +1,261 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ * Based on EP93xx wdt driver
+ */
+
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/watchdog.h>
+#include <linux/platform_device.h>
+#include <linux/uaccess.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <lantiq.h>
+
+/* Section 3.4 of the datasheet
+ * The password sequence protects the WDT control register from unintended
+ * write actions, which might cause malfunction of the WDT.
+ *
+ * essentially the following two magic passwords need to be written to allow
+ * IO access to the WDT core
+ */
+#define LTQ_WDT_PW1 0x00BE0000
+#define LTQ_WDT_PW2 0x00DC0000
+
+#define LTQ_WDT_CR 0x0 /* watchdog control register */
+#define LTQ_WDT_SR 0x8 /* watchdog status register */
+
+#define LTQ_WDT_SR_EN (0x1 << 31) /* enable bit */
+#define LTQ_WDT_SR_PWD (0x3 << 26) /* turn on power */
+#define LTQ_WDT_SR_CLKDIV (0x3 << 24) /* turn on clock and set */
+ /* divider to 0x40000 */
+#define LTQ_WDT_DIVIDER 0x40000
+#define LTQ_MAX_TIMEOUT ((1 << 16) - 1) /* the reload field is 16 bit */
+
+static int nowayout = WATCHDOG_NOWAYOUT;
+
+static void __iomem *ltq_wdt_membase;
+static unsigned long ltq_io_region_clk_rate;
+
+static unsigned long ltq_wdt_bootstatus;
+static unsigned long ltq_wdt_in_use;
+static int ltq_wdt_timeout = 30;
+static int ltq_wdt_ok_to_close;
+
+static void
+ltq_wdt_enable(void)
+{
+ ltq_wdt_timeout = ltq_wdt_timeout *
+ (ltq_io_region_clk_rate / LTQ_WDT_DIVIDER) + 0x1000;
+ if (ltq_wdt_timeout > LTQ_MAX_TIMEOUT)
+ ltq_wdt_timeout = LTQ_MAX_TIMEOUT;
+
+ /* write the first password magic */
+ ltq_w32(LTQ_WDT_PW1, ltq_wdt_membase + LTQ_WDT_CR);
+ /* write the second magic plus the configuration and new timeout */
+ ltq_w32(LTQ_WDT_SR_EN | LTQ_WDT_SR_PWD | LTQ_WDT_SR_CLKDIV |
+ LTQ_WDT_PW2 | ltq_wdt_timeout, ltq_wdt_membase + LTQ_WDT_CR);
+}
+
+static void
+ltq_wdt_disable(void)
+{
+ /* write the first password magic */
+ ltq_w32(LTQ_WDT_PW1, ltq_wdt_membase + LTQ_WDT_CR);
+ /* write the second password magic with no config
+ * this turns the watchdog off
+ */
+ ltq_w32(LTQ_WDT_PW2, ltq_wdt_membase + LTQ_WDT_CR);
+}
+
+static ssize_t
+ltq_wdt_write(struct file *file, const char __user *data,
+ size_t len, loff_t *ppos)
+{
+ if (len) {
+ if (!nowayout) {
+ size_t i;
+
+ ltq_wdt_ok_to_close = 0;
+ for (i = 0; i != len; i++) {
+ char c;
+
+ if (get_user(c, data + i))
+ return -EFAULT;
+ if (c == 'V')
+ ltq_wdt_ok_to_close = 1;
+ else
+ ltq_wdt_ok_to_close = 0;
+ }
+ }
+ ltq_wdt_enable();
+ }
+
+ return len;
+}
+
+static struct watchdog_info ident = {
+ .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
+ WDIOF_CARDRESET,
+ .identity = "ltq_wdt",
+};
+
+static long
+ltq_wdt_ioctl(struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ int ret = -ENOTTY;
+
+ switch (cmd) {
+ case WDIOC_GETSUPPORT:
+ ret = copy_to_user((struct watchdog_info __user *)arg, &ident,
+ sizeof(ident)) ? -EFAULT : 0;
+ break;
+
+ case WDIOC_GETBOOTSTATUS:
+ ret = put_user(ltq_wdt_bootstatus, (int __user *)arg);
+ break;
+
+ case WDIOC_GETSTATUS:
+ ret = put_user(0, (int __user *)arg);
+ break;
+
+ case WDIOC_SETTIMEOUT:
+ ret = get_user(ltq_wdt_timeout, (int __user *)arg);
+ if (!ret)
+ ltq_wdt_enable();
+ /* intentional drop through */
+ case WDIOC_GETTIMEOUT:
+ ret = put_user(ltq_wdt_timeout, (int __user *)arg);
+ break;
+
+ case WDIOC_KEEPALIVE:
+ ltq_wdt_enable();
+ ret = 0;
+ break;
+ }
+ return ret;
+}
+
+static int
+ltq_wdt_open(struct inode *inode, struct file *file)
+{
+ if (test_and_set_bit(0, &ltq_wdt_in_use))
+ return -EBUSY;
+ ltq_wdt_in_use = 1;
+ ltq_wdt_enable();
+
+ return nonseekable_open(inode, file);
+}
+
+static int
+ltq_wdt_release(struct inode *inode, struct file *file)
+{
+ if (ltq_wdt_ok_to_close)
+ ltq_wdt_disable();
+ else
+ pr_err("ltq_wdt: watchdog closed without warning\n");
+ ltq_wdt_ok_to_close = 0;
+ clear_bit(0, &ltq_wdt_in_use);
+
+ return 0;
+}
+
+static const struct file_operations ltq_wdt_fops = {
+ .owner = THIS_MODULE,
+ .write = ltq_wdt_write,
+ .unlocked_ioctl = ltq_wdt_ioctl,
+ .open = ltq_wdt_open,
+ .release = ltq_wdt_release,
+ .llseek = no_llseek,
+};
+
+static struct miscdevice ltq_wdt_miscdev = {
+ .minor = WATCHDOG_MINOR,
+ .name = "watchdog",
+ .fops = &ltq_wdt_fops,
+};
+
+static int __init
+ltq_wdt_probe(struct platform_device *pdev)
+{
+ struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ struct clk *clk;
+
+ if (!res) {
+ dev_err(&pdev->dev, "cannot obtain I/O memory region");
+ return -ENOENT;
+ }
+ res = devm_request_mem_region(&pdev->dev, res->start,
+ resource_size(res), dev_name(&pdev->dev));
+ if (!res) {
+ dev_err(&pdev->dev, "cannot request I/O memory region");
+ return -EBUSY;
+ }
+ ltq_wdt_membase = devm_ioremap_nocache(&pdev->dev, res->start,
+ resource_size(res));
+ if (!ltq_wdt_membase) {
+ dev_err(&pdev->dev, "cannot remap I/O memory region\n");
+ return -ENOMEM;
+ }
+
+ /* we do not need to enable the clock as it is always running */
+ clk = clk_get(&pdev->dev, "io");
+ WARN_ON(!clk);
+ ltq_io_region_clk_rate = clk_get_rate(clk);
+ clk_put(clk);
+
+ if (ltq_reset_cause() == LTQ_RST_CAUSE_WDTRST)
+ ltq_wdt_bootstatus = WDIOF_CARDRESET;
+
+ return misc_register(&ltq_wdt_miscdev);
+}
+
+static int __devexit
+ltq_wdt_remove(struct platform_device *pdev)
+{
+ misc_deregister(&ltq_wdt_miscdev);
+
+ if (ltq_wdt_membase)
+ iounmap(ltq_wdt_membase);
+
+ return 0;
+}
+
+
+static struct platform_driver ltq_wdt_driver = {
+ .remove = __devexit_p(ltq_wdt_remove),
+ .driver = {
+ .name = "ltq_wdt",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init
+init_ltq_wdt(void)
+{
+ return platform_driver_probe(&ltq_wdt_driver, ltq_wdt_probe);
+}
+
+static void __exit
+exit_ltq_wdt(void)
+{
+ return platform_driver_unregister(&ltq_wdt_driver);
+}
+
+module_init(init_ltq_wdt);
+module_exit(exit_ltq_wdt);
+
+module_param(nowayout, int, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
+
+MODULE_AUTHOR("John Crispin <blogic@openwrt.org>");
+MODULE_DESCRIPTION("Lantiq SoC Watchdog");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);

View File

@ -1,32 +0,0 @@
--- a/arch/mips/lantiq/xway/mach-easy50601.c
+++ b/arch/mips/lantiq/xway/mach-easy50601.c
@@ -32,12 +32,7 @@ static struct mtd_partition easy50601_pa
{
.name = "linux",
.offset = 0x20000,
- .size = 0xE0000,
- },
- {
- .name = "rootfs",
- .offset = 0x100000,
- .size = 0x300000,
+ .size = 0x3d0000,
},
};
--- a/arch/mips/lantiq/xway/mach-easy50712.c
+++ b/arch/mips/lantiq/xway/mach-easy50712.c
@@ -34,12 +34,7 @@ static struct mtd_partition easy50712_pa
{
.name = "linux",
.offset = 0x20000,
- .size = 0xe0000,
- },
- {
- .name = "rootfs",
- .offset = 0x100000,
- .size = 0x300000,
+ .size = 0x3d0000,
},
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,828 +0,0 @@
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -82,5 +82,6 @@ obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
obj-$(CONFIG_I2C_STUB) += i2c-stub.o
obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o
+obj-$(CONFIG_I2C_FALCON) += i2c-falcon.o
ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -282,6 +282,10 @@ config I2C_POWERMAC
comment "I2C system bus drivers (mostly embedded / system-on-chip)"
+config I2C_FALCON
+ tristate "Falcon I2C interface"
+# depends on SOC_FALCON
+
config I2C_AT91
tristate "Atmel AT91 I2C Two-Wire interface (TWI)"
depends on ARCH_AT91 && EXPERIMENTAL && BROKEN
--- /dev/null
+++ b/drivers/i2c/busses/i2c-falcon.c
@@ -0,0 +1,803 @@
+/*
+ * 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.
+ */
+
+/* #define DEBUG */
+
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+
+/* CURRENT ISSUES:
+ * - no high speed support
+ * - rx issue with "address mode" & "tx end" interrupts
+ * - ten bit mode is not tested
+ */
+
+/* mapping for access macros */
+#define reg_r32(reg) __raw_readl(reg)
+#define reg_w32(val, reg) __raw_writel(val, reg)
+#define reg_w32_mask(clear, set, reg) \
+ reg_w32((reg_r32(reg) & ~(clear)) | (set), reg)
+#define reg_r32_table(reg, idx) reg_r32(&((uint32_t *)&reg)[idx])
+#define reg_w32_table(val, reg, idx) reg_w32(val, &((uint32_t *)&reg)[idx])
+#define i2c (priv->membase)
+#include <falcon/i2c_reg.h>
+
+/* enable hacks to overcome current issue */
+#define FALCON_FIX_ME
+
+#define FALCON_I2C_ADDR 0x00
+#define FALCON_I2C_READY_TIMEOUT 1000
+#define FALCON_I2C_WAIT_TIMEOUT 10
+
+#define DRV_NAME "i2c-falcon"
+
+#if defined(DEBUG)
+#define static /* no static functions for better debugging */
+#endif
+
+#define FALCON_I2C_ARB_LOST (1 << 0)
+#define FALCON_I2C_NACK (1 << 1)
+#define FALCON_I2C_RX_UFL (1 << 2)
+#define FALCON_I2C_RX_OFL (1 << 3)
+#define FALCON_I2C_TX_UFL (1 << 4)
+#define FALCON_I2C_TX_OFL (1 << 5)
+#define FALCON_I2C_BURST_REQ (1 << 6)
+#define FALCON_I2C_RX (1 << 7)
+#define FALCON_I2C_TX_END (1 << 8)
+#define FALCON_I2C_ADDR_MATCH (1 << 9) /* doesn't trigger */
+
+struct falcon_i2c {
+ spinlock_t lock;
+
+ enum {
+ FALCON_I2C_MODE_100 = 1,
+ FALCON_I2C_MODE_400 = 2,
+ FALCON_I2C_MODE_3400 = 3
+ } mode; /* current speed mode */
+
+ int ten_bit; /* current address mode */
+ unsigned long status; /* bus events holder */
+ struct clk *clk; /* clock input for i2c hardware block */
+ struct gpon_reg_i2c __iomem *membase; /* base of mapped registers */
+ int irq_lb, irq_b, irq_err, irq_p; /* last burst, burst, error,
+ protocol IRQs */
+ struct completion done;
+ struct i2c_adapter adap;
+ struct device *dev;
+};
+
+#define FALCON_I2C_ERROR_MASK (FALCON_I2C_NACK \
+ | FALCON_I2C_ARB_LOST \
+ | FALCON_I2C_RX_OFL \
+ | FALCON_I2C_RX_UFL \
+ | FALCON_I2C_TX_OFL \
+ | FALCON_I2C_TX_UFL)
+
+#define FALCON_I2C_ERROR(priv) (priv->status & FALCON_I2C_ERROR_MASK)
+#define FALCON_I2C_ERROR_CLEAR(priv) do { \
+ priv->status &= \
+ ~FALCON_I2C_ERROR_MASK; \
+ } while (0)
+
+static void falcon_addr_configure(struct falcon_i2c *priv, int ten_bit)
+{
+ u32 ten_bit_mask = ten_bit ? I2C_ADDR_CFG_TBAM_10bit : 0;
+
+ /* configure address */
+ i2c_w32(I2C_ADDR_CFG_SOPE_EN /* generate stop when no more data in the
+ fifo */
+ | I2C_ADDR_CFG_SONA_EN /* generate stop when NA received */
+ | I2C_ADDR_CFG_MnS_EN /* we are master device */
+ | ten_bit_mask
+ | FALCON_I2C_ADDR, /* our address */
+ addr_cfg);
+}
+
+static irqreturn_t falcon_i2c_isr(int irq, void *dev_id)
+{
+ u32 i_raw, i_pro, i_err;
+ struct falcon_i2c *priv = dev_id;
+ unsigned long flags;
+ unsigned int old_status;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ old_status = (unsigned int)priv->status;
+
+ i_raw = i2c_r32(mis);
+
+ /* protocol interrupt */
+ if (i_raw & I2C_RIS_I2C_P_INT_INTOCC) {
+ i_pro = i2c_r32(p_irqss);
+
+ /* tx -> rx switch */
+ if (i_pro & I2C_P_IRQSS_RX)
+ priv->status |= FALCON_I2C_RX;
+
+ /* tx end */
+ if (i_pro & I2C_P_IRQSS_TX_END)
+ priv->status |= FALCON_I2C_TX_END;
+
+ /* not acknowledge */
+ if (i_pro & I2C_P_IRQSS_NACK)
+ priv->status |= FALCON_I2C_NACK;
+
+ /* arbitration lost */
+ if (i_pro & I2C_P_IRQSS_AL)
+ priv->status |= FALCON_I2C_ARB_LOST;
+
+ /* address match */
+ if (i_pro & I2C_P_IRQSS_AM)
+ priv->status |= FALCON_I2C_ADDR_MATCH;
+
+ i2c_w32(i_pro, p_irqsc);
+ }
+
+ /* error interrupt */
+ if (i_raw & I2C_RIS_I2C_ERR_INT_INTOCC) {
+ i_err = i2c_r32(err_irqss);
+
+ /* tx fifo overflow */
+ if (i_err & I2C_ERR_IRQSS_TXF_OFL)
+ priv->status |= FALCON_I2C_TX_OFL;
+
+ /* tx fifo underflow */
+ if (i_err & I2C_ERR_IRQSS_TXF_UFL)
+ priv->status |= FALCON_I2C_TX_UFL;
+
+ /* rx fifo overflow */
+ if (i_err & I2C_ERR_IRQSS_RXF_OFL)
+ priv->status |= FALCON_I2C_RX_OFL;
+
+ /* rx fifo underflow */
+ if (i_err & I2C_ERR_IRQSS_RXF_UFL)
+ priv->status |= FALCON_I2C_RX_UFL;
+
+ i2c_w32(i_err, err_irqsc);
+ }
+
+ /* burst request */
+ if (i_raw & I2C_RIS_BREQ_INT_INTOCC) {
+ i2c_w32_mask(I2C_IMSC_BREQ_INT_EN, 0, imsc);
+ i2c_w32_mask(0, I2C_ICR_BREQ_INT_CLR, icr);
+
+ priv->status |= FALCON_I2C_BURST_REQ;
+ }
+
+ /* last burst request */
+ if (i_raw & I2C_RIS_LBREQ_INT_INTOCC) {
+ i2c_w32_mask(I2C_IMSC_LBREQ_INT_EN, 0, imsc);
+ i2c_w32_mask(0, I2C_ICR_LBREQ_INT_CLR, icr);
+
+ priv->status |= FALCON_I2C_BURST_REQ;
+ }
+
+ if (old_status != (unsigned int)priv->status)
+ complete(&priv->done);
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+static int falcon_i2c_ready(struct falcon_i2c *priv)
+{
+ int timeout;
+ u32 bus_stat;
+ unsigned long flags;
+ int ret;
+
+ for (timeout = 0; timeout < FALCON_I2C_READY_TIMEOUT; timeout++) {
+ bus_stat = i2c_r32(bus_stat);
+
+ if (bus_stat & I2C_BUS_STAT_BS_SC) {
+ cpu_relax();
+ } else {
+ spin_lock_irqsave(&priv->lock, flags);
+
+ if (FALCON_I2C_ERROR(priv)) {
+ ret = priv->status;
+
+ dev_dbg(priv->dev, "bus ready wait error 0x%08lx\n", priv->status);
+
+ FALCON_I2C_ERROR_CLEAR(priv);
+ } else {
+ ret = 0;
+ }
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return ret;
+ }
+ }
+
+ dev_dbg(priv->dev, "bus ready wait timeout\n");
+
+ return -ETIME;
+}
+
+static int falcon_i2c_wait(struct falcon_i2c *priv, unsigned long status)
+{
+ int ret = 0;
+ unsigned long flags;
+ unsigned int timeout;
+
+ spin_lock_irqsave(&priv->lock, flags);
+
+ priv->status &= FALCON_I2C_BURST_REQ;
+
+ /* check if the event already occurred */
+ if ((priv->status & status) == status) {
+ priv->status &= ~status;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+ }
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ /* unmask burst interrupts */
+ i2c_w32_mask(0, I2C_IMSC_LBREQ_INT_EN | I2C_IMSC_BREQ_INT_EN, imsc);
+
+ for (timeout = 0; timeout < FALCON_I2C_WAIT_TIMEOUT; timeout++) {
+ /* wait for the data request */
+ wait_for_completion_timeout(&priv->done, HZ / 10);
+
+ /* handle errors */
+ spin_lock_irqsave(&priv->lock, flags);
+
+ if (FALCON_I2C_ERROR(priv)) {
+ dev_dbg(priv->dev, "wait error 0x%08lx (waiting for 0x%08lx)\n",
+ priv->status,
+ status);
+
+ if (priv->status & FALCON_I2C_NACK)
+ ret = -ENXIO;
+ else
+ ret = -EREMOTEIO;
+
+ FALCON_I2C_ERROR_CLEAR(priv);
+ } else {
+ if ((priv->status & status) == status) {
+ priv->status &= ~status;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ return 0;
+ }
+ }
+
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ if (ret)
+ return ret;
+ }
+
+ dev_dbg(priv->dev, "wait timeout error 0x%08lx (waiting for 0x%08lx)\n",
+ priv->status,
+ status);
+
+ return -ETIME;
+}
+
+static int falcon_i2c_tx(struct falcon_i2c *priv, int ten_bit, u16 addr,
+ u8 *buf, int len)
+{
+ int i;
+ int ret;
+
+ dev_dbg(priv->dev, "%s\n", __func__);
+
+ /* tell fifo the number of bytes we are going to send */
+ i2c_w32(len + (ten_bit ? 2 : 1), tps_ctrl);
+
+ /* wait for the data request */
+ ret = falcon_i2c_wait(priv, FALCON_I2C_BURST_REQ);
+ if (ret)
+ return ret;
+
+ /* send slave address */
+ if (ten_bit) {
+ i2c_w32(0x78 | ((addr >> 7) & 0x7), txd);
+ i2c_w32(0x78 | ((addr & 0x7f) << 1) | 0, txd);
+ } else {
+ i2c_w32((addr << 1) | 0, txd);
+ }
+
+ /* fill fifo */
+ for (i = 0; i < len; i++) {
+ ret = falcon_i2c_wait(priv, FALCON_I2C_BURST_REQ);
+ if (ret)
+ return ret;
+
+ i2c_w32(buf[i], txd);
+ }
+
+ return falcon_i2c_wait(priv, FALCON_I2C_TX_END);
+}
+
+static int falcon_i2c_rx(struct falcon_i2c *priv, int ten_bit, u16 addr,
+ u8 *buf, int len)
+{
+ int i;
+ int ret;
+
+ dev_dbg(priv->dev, "%s\n", __func__);
+
+ /* we need to transmit address only */
+ i2c_w32(ten_bit ? 2 : 1, tps_ctrl);
+
+ /* set maximum received packet size */
+ i2c_w32(len, mrps_ctrl);
+
+ /* wait for the data request */
+ ret = falcon_i2c_wait(priv, FALCON_I2C_BURST_REQ);
+ if (ret)
+ return ret;
+
+ /* write down the address */
+ if (ten_bit) {
+ i2c_w32(0x78 | ((addr >> 7) & 0x7), txd);
+ i2c_w32(0x78 | ((addr & 0x7f) << 1) | 1, txd);
+ } else {
+ i2c_w32((addr << 1) | 1, txd);
+ }
+
+ /* wait for the read request */
+ ret = falcon_i2c_wait(priv, FALCON_I2C_TX_END
+#ifndef FALCON_FIX_ME
+ | FALCON_I2C_ADDR_MATCH
+#endif
+ | FALCON_I2C_RX);
+
+ if (ret)
+ return ret;
+
+ /* read bytes */
+ for (i = 0; i < len; i++) {
+#ifdef FALCON_FIX_ME
+ while (i2c_r32(rps_stat) == 0)
+ cpu_relax();
+#else
+ ret = falcon_i2c_wait(priv, FALCON_I2C_BURST_REQ);
+
+ if (ret)
+ return ret;
+#endif
+
+ buf[i] = i2c_r32(rxd);
+ }
+
+#ifndef FALCON_FIX_ME
+ /* wait for transmission end */
+ return falcon_i2c_wait(priv, FALCON_I2C_TX_END);
+#else
+ return 0;
+#endif
+}
+
+static int falcon_i2c_xfer_msg(struct falcon_i2c *priv, struct i2c_msg *msg)
+{
+ int ret;
+ int ten_bit;
+ unsigned long flags;
+
+ dev_dbg(priv->dev, "%s %u byte(s) %s 0x%02x\n",
+ (msg->flags & I2C_M_RD) ? "read" : "write", msg->len,
+ (msg->flags & I2C_M_RD) ? "from" : "to", msg->addr);
+
+ if (msg->flags & I2C_M_TEN)
+ ten_bit = 1;
+ else
+ ten_bit = 0;
+
+ /* reconfigure bus if need to send message in different address mode */
+ spin_lock_irqsave(&priv->lock, flags);
+ if (ten_bit != priv->ten_bit) {
+
+ /* disable bus */
+ i2c_w32_mask(I2C_RUN_CTRL_RUN_EN, 0, run_ctrl);
+
+ /* reconfigure address */
+ falcon_addr_configure(priv, ten_bit);
+
+ /* enable bus */
+ i2c_w32_mask(0, I2C_RUN_CTRL_RUN_EN, run_ctrl);
+
+ priv->ten_bit = ten_bit;
+ }
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ /* read/write actual message */
+ if (msg->flags & I2C_M_RD)
+ ret = falcon_i2c_rx(priv, ten_bit, msg->addr, msg->buf,
+ msg->len);
+ else
+ ret = falcon_i2c_tx(priv, ten_bit, msg->addr, msg->buf,
+ msg->len);
+
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int falcon_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
+ int num)
+{
+ int i;
+ int ret;
+ unsigned long flags;
+ struct falcon_i2c *priv = i2c_get_adapdata(adap);
+
+ dev_dbg(priv->dev, "xfer %u messages\n", num);
+
+ /* transfer each message */
+ for (i = 0; i < num; i++) {
+#ifdef FALCON_FIX_ME
+ /* disable bus */
+ i2c_w32_mask(I2C_RUN_CTRL_RUN_EN, 0, run_ctrl);
+ /* enable bus */
+ i2c_w32_mask(0, I2C_RUN_CTRL_RUN_EN, run_ctrl);
+#endif
+
+ /* clear bus status */
+ spin_lock_irqsave(&priv->lock, flags);
+ priv->status = 0;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ /* wait for the bus to become ready */
+ ret = falcon_i2c_ready(priv);
+ if (ret)
+ return ret;
+
+ /* transfer message */
+ ret = falcon_i2c_xfer_msg(priv, &msg[i]);
+
+ if (ret)
+ return ret;
+
+ /* check for unhandled errors */
+ spin_lock_irqsave(&priv->lock, flags);
+ if (FALCON_I2C_ERROR(priv))
+ ret = priv->status;
+ spin_unlock_irqrestore(&priv->lock, flags);
+
+ if (ret) {
+ dev_warn(priv->dev, "message %u unhandled error 0x%x\n",
+ i, ret);
+
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static u32 falcon_i2c_func(struct i2c_adapter *adap)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm falcon_i2c_algorithm = {
+ .master_xfer = falcon_i2c_xfer,
+ .functionality = falcon_i2c_func,
+};
+
+static int falcon_i2c_hw_init(struct i2c_adapter *adap)
+{
+ struct falcon_i2c *priv = i2c_get_adapdata(adap);
+
+ /* disable bus */
+ i2c_w32_mask(I2C_RUN_CTRL_RUN_EN, 0, run_ctrl);
+
+ /* set normal operation clock divider */
+ i2c_w32(1 << I2C_CLC_RMC_OFFSET, clc);
+
+ /* set frequency */
+ if (priv->mode == FALCON_I2C_MODE_100) {
+ dev_dbg(priv->dev, "set standard mode (100 kHz)\n");
+
+ i2c_w32(0, fdiv_high_cfg);
+
+ i2c_w32((1 << I2C_FDIV_CFG_INC_OFFSET)
+ | (499 << I2C_FDIV_CFG_DEC_OFFSET),
+ fdiv_cfg);
+ } else if (priv->mode == FALCON_I2C_MODE_400) {
+ dev_dbg(priv->dev, "set fast mode (400 kHz)\n");
+
+ i2c_w32(0, fdiv_high_cfg);
+
+ i2c_w32((1 << I2C_FDIV_CFG_INC_OFFSET)
+ | (124 << I2C_FDIV_CFG_DEC_OFFSET),
+ fdiv_cfg);
+ } else if (priv->mode == FALCON_I2C_MODE_3400) {
+ dev_dbg(priv->dev, "set high mode (3.4 MHz)\n");
+
+ i2c_w32(0, fdiv_cfg);
+
+ /* TODO recalculate value for 100MHz input */
+ i2c_w32((41 << I2C_FDIV_CFG_INC_OFFSET)
+ | (152 << I2C_FDIV_CFG_DEC_OFFSET),
+ fdiv_high_cfg);
+ } else {
+ dev_warn(priv->dev, "unknown mode\n");
+
+ return -ENODEV;
+ }
+
+ /* configure fifo */
+ i2c_w32(I2C_FIFO_CFG_TXFC /* tx fifo as flow controller */
+ | I2C_FIFO_CFG_RXFC /* rx fifo as flow controller */
+ | I2C_FIFO_CFG_TXFA_TXFA2 /* tx fifo 4-byte aligned */
+ | I2C_FIFO_CFG_RXFA_RXFA2 /* rx fifo 4-byte aligned */
+ | I2C_FIFO_CFG_TXBS_TXBS0 /* tx fifo burst size is 1 word */
+ | I2C_FIFO_CFG_RXBS_RXBS0, /* rx fifo burst size is 1 word */
+ fifo_cfg);
+
+ /* configure address */
+ falcon_addr_configure(priv, priv->ten_bit);
+
+ /* enable bus */
+ i2c_w32_mask(0, I2C_RUN_CTRL_RUN_EN, run_ctrl);
+
+ /* mask burst interrupts */
+ i2c_w32_mask(I2C_IMSC_LBREQ_INT_EN | I2C_IMSC_BREQ_INT_EN, 0, imsc);
+
+ /* enable interrupts */
+ i2c_w32(I2C_IMSC_LBREQ_INT_EN
+ | I2C_IMSC_BREQ_INT_EN
+ | I2C_IMSC_I2C_P_INT_EN
+ | I2C_IMSC_I2C_ERR_INT_EN,
+ imsc);
+
+ return 0;
+}
+
+static int __devinit falcon_i2c_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct falcon_i2c *priv;
+ struct i2c_adapter *adap;
+ struct resource *mmres, *ioarea,
+ *irqres_lb, *irqres_b, *irqres_err, *irqres_p;
+ struct clk *clk;
+
+ dev_dbg(&pdev->dev, "probing\n");
+
+ mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ irqres_lb = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
+ "i2c_lb");
+ irqres_b = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "i2c_b");
+ irqres_err = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
+ "i2c_err");
+ irqres_p = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "i2c_p");
+
+ if (!mmres || !irqres_lb || !irqres_b || !irqres_err || !irqres_p) {
+ dev_err(&pdev->dev, "no resources\n");
+ return -ENODEV;
+ }
+
+ clk = clk_get(&pdev->dev, "fpi");
+ if (IS_ERR(clk)) {
+ dev_err(&pdev->dev, "failed to get fpi clk\n");
+ return -ENOENT;
+ }
+
+ if (clk_get_rate(clk) != 100000000) {
+ dev_err(&pdev->dev, "input clock is not 100MHz\n");
+ return -ENOENT;
+ }
+
+ /* allocate private data */
+ priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+ if (!priv) {
+ dev_err(&pdev->dev, "can't allocate private data\n");
+ return -ENOMEM;
+ }
+
+ adap = &priv->adap;
+ i2c_set_adapdata(adap, priv);
+ adap->owner = THIS_MODULE;
+ adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
+ strlcpy(adap->name, DRV_NAME "-adapter", sizeof(adap->name));
+ adap->algo = &falcon_i2c_algorithm;
+
+ priv->ten_bit = 0;
+ priv->mode = FALCON_I2C_MODE_100;
+ priv->clk = clk;
+ priv->dev = &pdev->dev;
+
+ spin_lock_init(&priv->lock);
+
+ ioarea = request_mem_region(mmres->start, resource_size(mmres),
+ pdev->name);
+
+ if (ioarea == NULL) {
+ dev_err(&pdev->dev, "I2C region already claimed\n");
+ ret = -ENXIO;
+ goto err_free_priv;
+ }
+
+ /* map memory */
+ priv->membase = ioremap_nocache(mmres->start & ~KSEG1,
+ resource_size(mmres));
+ if (priv->membase == NULL) {
+ ret = -ENOMEM;
+ goto err_release_region;
+ }
+
+ priv->irq_lb = irqres_lb->start;
+ ret = request_irq(priv->irq_lb, falcon_i2c_isr, IRQF_DISABLED,
+ irqres_lb->name, priv);
+ if (ret) {
+ dev_err(&pdev->dev, "can't get last burst IRQ %d\n", irqres_lb->start);
+ ret = -ENODEV;
+ goto err_unmap_mem;
+ }
+
+ priv->irq_b = irqres_b->start;
+ ret = request_irq(priv->irq_b, falcon_i2c_isr, IRQF_DISABLED,
+ irqres_b->name, priv);
+ if (ret) {
+ dev_err(&pdev->dev, "can't get burst IRQ %d\n", irqres_b->start);
+ ret = -ENODEV;
+ goto err_free_lb_irq;
+ }
+
+ priv->irq_err = irqres_err->start;
+ ret = request_irq(priv->irq_err, falcon_i2c_isr, IRQF_DISABLED,
+ irqres_err->name, priv);
+ if (ret) {
+ dev_err(&pdev->dev, "can't get error IRQ %d\n", irqres_err->start);
+ ret = -ENODEV;
+ goto err_free_b_irq;
+ }
+
+ priv->irq_p = irqres_p->start;
+ ret = request_irq(priv->irq_p, falcon_i2c_isr, IRQF_DISABLED,
+ irqres_p->name, priv);
+ if (ret) {
+ dev_err(&pdev->dev, "can't get protocol IRQ %d\n", irqres_p->start);
+ ret = -ENODEV;
+ goto err_free_err_irq;
+ }
+
+ dev_dbg(&pdev->dev, "mapped io-space to %p\n", priv->membase);
+ dev_dbg(&pdev->dev, "use IRQs %d, %d, %d, %d\n", irqres_lb->start,
+ irqres_b->start, irqres_err->start, irqres_p->start);
+
+ /* add our adapter to the i2c stack */
+ ret = i2c_add_numbered_adapter(adap);
+ if (ret) {
+ dev_err(&pdev->dev, "can't register I2C adapter\n");
+ goto err_free_p_irq;
+ }
+
+ platform_set_drvdata(pdev, priv);
+ i2c_set_adapdata(adap, priv);
+
+ /* print module version information */
+ dev_dbg(&pdev->dev, "module id=%u revision=%u\n",
+ (i2c_r32(id) & I2C_ID_ID_MASK) >> I2C_ID_ID_OFFSET,
+ (i2c_r32(id) & I2C_ID_REV_MASK) >> I2C_ID_REV_OFFSET);
+
+ init_completion(&priv->done);
+
+ /* initialize HW */
+ ret = falcon_i2c_hw_init(adap);
+ if (ret) {
+ dev_err(&pdev->dev, "can't configure adapter\n");
+ goto err_remove_adapter;
+ }
+
+ return 0;
+
+err_remove_adapter:
+ i2c_del_adapter(adap);
+ platform_set_drvdata(pdev, NULL);
+
+err_free_p_irq:
+ free_irq(priv->irq_p, priv);
+
+err_free_err_irq:
+ free_irq(priv->irq_err, priv);
+
+err_free_b_irq:
+ free_irq(priv->irq_b, priv);
+
+err_free_lb_irq:
+ free_irq(priv->irq_lb, priv);
+
+err_unmap_mem:
+ iounmap(priv->membase);
+
+err_release_region:
+ release_mem_region(mmres->start, resource_size(mmres));
+
+err_free_priv:
+ kfree(priv);
+
+ return ret;
+}
+
+static int __devexit falcon_i2c_remove(struct platform_device *pdev)
+{
+ struct falcon_i2c *priv = platform_get_drvdata(pdev);
+ struct resource *mmres;
+
+ /* disable bus */
+ i2c_w32_mask(I2C_RUN_CTRL_RUN_EN, 0, run_ctrl);
+
+ /* remove driver */
+ platform_set_drvdata(pdev, NULL);
+ i2c_del_adapter(&priv->adap);
+
+ free_irq(priv->irq_lb, priv);
+ free_irq(priv->irq_b, priv);
+ free_irq(priv->irq_err, priv);
+ free_irq(priv->irq_p, priv);
+
+ kfree(priv);
+
+ mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ release_mem_region(mmres->start, resource_size(mmres));
+
+ dev_dbg(&pdev->dev, "removed\n");
+
+ return 0;
+}
+
+static struct platform_driver falcon_i2c_driver = {
+ .probe = falcon_i2c_probe,
+ .remove = __devexit_p(falcon_i2c_remove),
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init falcon_i2c_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&falcon_i2c_driver);
+
+ if (ret)
+ printk(KERN_DEBUG DRV_NAME ": can't register platform driver");
+
+ return ret;
+}
+
+static void __exit falcon_i2c_exit(void)
+{
+ platform_driver_unregister(&falcon_i2c_driver);
+}
+
+module_init(falcon_i2c_init);
+module_exit(falcon_i2c_exit);
+
+MODULE_DESCRIPTION("Lantiq FALC(tm) ON - I2C bus adapter");
+MODULE_ALIAS("platform:i2c_falcon");
+MODULE_LICENSE("GPL");

View File

@ -1,497 +0,0 @@
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -55,6 +55,7 @@ obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.
obj-$(CONFIG_SPI_SH_MSIOF) += spi_sh_msiof.o
obj-$(CONFIG_SPI_STMP3XXX) += spi_stmp.o
obj-$(CONFIG_SPI_NUC900) += spi_nuc900.o
+obj-$(CONFIG_SPI_FALCON) += spi_falcon.o
# special build for s3c24xx spi driver with fiq support
spi_s3c24xx_hw-y := spi_s3c24xx.o
--- /dev/null
+++ b/drivers/spi/spi_falcon.c
@@ -0,0 +1,471 @@
+/*
+ * 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 <linux/module.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/delay.h>
+#include <linux/workqueue.h>
+
+#include <lantiq.h> /* ebu_lock */
+#include <falcon/ebu_reg.h>
+#include <falcon/sys1_reg.h>
+
+#define DRV_NAME "falcon_spi"
+
+#define FALCON_SPI_XFER_BEGIN (1 << 0)
+#define FALCON_SPI_XFER_END (1 << 1)
+
+/* mapping for access macros */
+#define reg_r32(reg) __raw_readl(reg)
+#define reg_w32(val, reg) __raw_writel(val, reg)
+#define reg_w32_mask(clear, set, reg) reg_w32((reg_r32(reg) \
+ & ~(clear)) | (set), reg)
+#define reg_r32_table(reg, idx) reg_r32(&((uint32_t *)&reg)[idx])
+#define reg_w32_table(val, reg, idx) reg_w32(val, &((uint32_t *)&reg)[idx])
+
+#define ebu (priv->ebu_membase)
+#define sys1 (priv->sys1_membase)
+
+struct falcon_spi {
+ u32 sfcmd; /* for caching of opcode, direction, ... */
+
+ struct spi_master *master;
+
+ struct gpon_reg_ebu __iomem *ebu_membase;
+ struct gpon_reg_sys1 __iomem *sys1_membase;
+};
+
+int falcon_spi_xfer(struct spi_device *spi,
+ struct spi_transfer *t,
+ unsigned long flags)
+{
+ struct device *dev = &spi->dev;
+ struct falcon_spi *priv = spi_master_get_devdata(spi->master);
+ const u8 *txp = t->tx_buf;
+ u8 *rxp = t->rx_buf;
+ unsigned int bytelen = ((8 * t->len + 7) / 8);
+ unsigned int len, alen, dumlen;
+ u32 val;
+ enum {
+ state_init,
+ state_command_prepare,
+ state_write,
+ state_read,
+ state_disable_cs,
+ state_end
+ } state = state_init;
+
+ do {
+ switch (state) {
+ case state_init: /* detect phase of upper layer sequence */
+ {
+ /* initial write ? */
+ if (flags & FALCON_SPI_XFER_BEGIN) {
+ if (!txp) {
+ dev_err(dev,
+ "BEGIN without tx data!\n");
+ return -1;
+ }
+ /*
+ * Prepare the parts of the sfcmd register,
+ * which should not
+ * change during a sequence!
+ * Only exception are the length fields,
+ * especially alen and dumlen.
+ */
+
+ priv->sfcmd = ((spi->chip_select
+ << SFCMD_CS_OFFSET)
+ & SFCMD_CS_MASK);
+ priv->sfcmd |= SFCMD_KEEP_CS_KEEP_SELECTED;
+ priv->sfcmd |= *txp;
+ txp++;
+ bytelen--;
+ if (bytelen) {
+ /* more data:
+ * maybe address and/or dummy */
+ state = state_command_prepare;
+ break;
+ } else {
+ dev_dbg(dev, "write cmd %02X\n",
+ priv->sfcmd & SFCMD_OPC_MASK);
+ }
+ }
+ /* continued write ? */
+ if (txp && bytelen) {
+ state = state_write;
+ break;
+ }
+ /* read data? */
+ if (rxp && bytelen) {
+ state = state_read;
+ break;
+ }
+ /* end of sequence? */
+ if (flags & FALCON_SPI_XFER_END)
+ state = state_disable_cs;
+ else
+ state = state_end;
+ break;
+ }
+ case state_command_prepare: /* collect tx data for
+ address and dummy phase */
+ {
+ /* txp is valid, already checked */
+ val = 0;
+ alen = 0;
+ dumlen = 0;
+ while (bytelen > 0) {
+ if (alen < 3) {
+ val = (val<<8)|(*txp++);
+ alen++;
+ } else if ((dumlen < 15) && (*txp == 0)) {
+ /*
+ * assume dummy bytes are set to 0
+ * from upper layer
+ */
+ dumlen++;
+ txp++;
+ } else
+ break;
+ bytelen--;
+ }
+ priv->sfcmd &= ~(SFCMD_ALEN_MASK | SFCMD_DUMLEN_MASK);
+ priv->sfcmd |= (alen << SFCMD_ALEN_OFFSET) |
+ (dumlen << SFCMD_DUMLEN_OFFSET);
+ if (alen > 0)
+ ebu_w32(val, sfaddr);
+
+ dev_dbg(dev, "write cmd %02X, alen=%d "
+ "(addr=%06X) dumlen=%d\n",
+ priv->sfcmd & SFCMD_OPC_MASK,
+ alen, val, dumlen);
+
+ if (bytelen > 0) {
+ /* continue with write */
+ state = state_write;
+ } else if (flags & FALCON_SPI_XFER_END) {
+ /* end of sequence? */
+ state = state_disable_cs;
+ } else {
+ /* go to end and expect another
+ * call (read or write) */
+ state = state_end;
+ }
+ break;
+ }
+ case state_write:
+ {
+ /* txp still valid */
+ priv->sfcmd |= SFCMD_DIR_WRITE;
+ len = 0;
+ val = 0;
+ do {
+ if (bytelen--)
+ val |= (*txp++) << (8 * len++);
+ if ((flags & FALCON_SPI_XFER_END)
+ && (bytelen == 0)) {
+ priv->sfcmd &=
+ ~SFCMD_KEEP_CS_KEEP_SELECTED;
+ }
+ if ((len == 4) || (bytelen == 0)) {
+ ebu_w32(val, sfdata);
+ ebu_w32(priv->sfcmd
+ | (len<<SFCMD_DLEN_OFFSET),
+ sfcmd);
+ len = 0;
+ val = 0;
+ priv->sfcmd &= ~(SFCMD_ALEN_MASK
+ | SFCMD_DUMLEN_MASK);
+ }
+ } while (bytelen);
+ state = state_end;
+ break;
+ }
+ case state_read:
+ {
+ /* read data */
+ priv->sfcmd &= ~SFCMD_DIR_WRITE;
+ do {
+ if ((flags & FALCON_SPI_XFER_END)
+ && (bytelen <= 4)) {
+ priv->sfcmd &=
+ ~SFCMD_KEEP_CS_KEEP_SELECTED;
+ }
+ len = (bytelen > 4) ? 4 : bytelen;
+ bytelen -= len;
+ ebu_w32(priv->sfcmd
+ |(len<<SFCMD_DLEN_OFFSET), sfcmd);
+ priv->sfcmd &= ~(SFCMD_ALEN_MASK
+ | SFCMD_DUMLEN_MASK);
+ do {
+ val = ebu_r32(sfstat);
+ if (val & SFSTAT_CMD_ERR) {
+ /* reset error status */
+ dev_err(dev, "SFSTAT: CMD_ERR "
+ "(%x)\n", val);
+ ebu_w32(SFSTAT_CMD_ERR, sfstat);
+ return -1;
+ }
+ } while (val & SFSTAT_CMD_PEND);
+ val = ebu_r32(sfdata);
+ do {
+ *rxp = (val & 0xFF);
+ rxp++;
+ val >>= 8;
+ len--;
+ } while (len);
+ } while (bytelen);
+ state = state_end;
+ break;
+ }
+ case state_disable_cs:
+ {
+ priv->sfcmd &= ~SFCMD_KEEP_CS_KEEP_SELECTED;
+ ebu_w32(priv->sfcmd | (0<<SFCMD_DLEN_OFFSET), sfcmd);
+ val = ebu_r32(sfstat);
+ if (val & SFSTAT_CMD_ERR) {
+ /* reset error status */
+ dev_err(dev, "SFSTAT: CMD_ERR (%x)\n", val);
+ ebu_w32(SFSTAT_CMD_ERR, sfstat);
+ return -1;
+ }
+ state = state_end;
+ break;
+ }
+ case state_end:
+ break;
+ }
+ } while (state != state_end);
+
+ return 0;
+}
+
+static int falcon_spi_setup(struct spi_device *spi)
+{
+ struct device *dev = &spi->dev;
+ struct falcon_spi *priv = spi_master_get_devdata(spi->master);
+ const u32 ebuclk = 100*1000*1000;
+ unsigned int i;
+ unsigned long flags;
+
+ dev_dbg(dev, "setup\n");
+
+ if (spi->master->bus_num > 0 || spi->chip_select > 0)
+ return -ENODEV;
+
+ spin_lock_irqsave(&ebu_lock, flags);
+
+ if (ebuclk < spi->max_speed_hz) {
+ /* set EBU clock to 100 MHz */
+ sys1_w32_mask(0, EBUCC_EBUDIV_SELF100, ebucc);
+ i = 1; /* divider */
+ } else {
+ /* set EBU clock to 50 MHz */
+ sys1_w32_mask(EBUCC_EBUDIV_SELF100, 0, ebucc);
+
+ /* search for suitable divider */
+ for (i = 1; i < 7; i++) {
+ if (ebuclk / i <= spi->max_speed_hz)
+ break;
+ }
+ }
+
+ /* setup period of serial clock */
+ ebu_w32_mask(SFTIME_SCKF_POS_MASK
+ | SFTIME_SCKR_POS_MASK
+ | SFTIME_SCK_PER_MASK,
+ (i << SFTIME_SCKR_POS_OFFSET)
+ | (i << (SFTIME_SCK_PER_OFFSET + 1)),
+ sftime);
+
+ /* set some bits of unused_wd, to not trigger HOLD/WP
+ * signals on non QUAD flashes */
+ ebu_w32((SFIO_UNUSED_WD_MASK & (0x8|0x4)), sfio);
+
+ ebu_w32(BUSRCON0_AGEN_SERIAL_FLASH | BUSRCON0_PORTW_8_BIT_MUX,
+ busrcon0);
+ ebu_w32(BUSWCON0_AGEN_SERIAL_FLASH, buswcon0);
+ /* set address wrap around to maximum for 24-bit addresses */
+ ebu_w32_mask(SFCON_DEV_SIZE_MASK, SFCON_DEV_SIZE_A23_0, sfcon);
+
+ spin_unlock_irqrestore(&ebu_lock, flags);
+
+ return 0;
+}
+
+static int falcon_spi_transfer(struct spi_device *spi, struct spi_message *m)
+{
+ struct falcon_spi *priv = spi_master_get_devdata(spi->master);
+ struct spi_transfer *t;
+ unsigned long spi_flags;
+ unsigned long flags;
+ int ret = 0;
+
+ priv->sfcmd = 0;
+ m->actual_length = 0;
+
+ spi_flags = FALCON_SPI_XFER_BEGIN;
+ list_for_each_entry(t, &m->transfers, transfer_list) {
+ if (list_is_last(&t->transfer_list, &m->transfers))
+ spi_flags |= FALCON_SPI_XFER_END;
+
+ spin_lock_irqsave(&ebu_lock, flags);
+ ret = falcon_spi_xfer(spi, t, spi_flags);
+ spin_unlock_irqrestore(&ebu_lock, flags);
+
+ if (ret)
+ break;
+
+ m->actual_length += t->len;
+
+ if (t->delay_usecs || t->cs_change)
+ BUG();
+
+ spi_flags = 0;
+ }
+
+ m->status = ret;
+ m->complete(m->context);
+
+ return 0;
+}
+
+static void falcon_spi_cleanup(struct spi_device *spi)
+{
+ struct device *dev = &spi->dev;
+
+ dev_dbg(dev, "cleanup\n");
+}
+
+static int __devinit falcon_spi_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct falcon_spi *priv;
+ struct spi_master *master;
+ struct resource *memres_ebu, *memres_sys1;
+ int ret;
+
+ dev_dbg(dev, "probing\n");
+
+ memres_ebu = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ebu");
+ memres_sys1 = platform_get_resource_byname(pdev, IORESOURCE_MEM,
+ "sys1");
+
+ if (!memres_ebu || !memres_sys1) {
+ dev_err(dev, "no resources\n");
+ return -ENODEV;
+ }
+
+ master = spi_alloc_master(&pdev->dev, sizeof(*priv));
+ if (!master) {
+ dev_err(dev, "no memory for spi_master\n");
+ return -ENOMEM;
+ }
+
+ priv = spi_master_get_devdata(master);
+
+ priv->ebu_membase = ioremap_nocache(memres_ebu->start & ~KSEG1,
+ resource_size(memres_ebu));
+
+ if (!priv->ebu_membase) {
+ dev_err(dev, "can't map ebu memory\n");
+
+ ret = -ENOMEM;
+ goto free_master;
+ }
+
+ priv->sys1_membase = ioremap_nocache(memres_sys1->start & ~KSEG1,
+ resource_size(memres_sys1));
+
+ if (!priv->sys1_membase) {
+ dev_err(dev, "can't map sys1 memory\n");
+
+ ret = -ENOMEM;
+ goto unmap_ebu;
+ }
+
+ priv->master = master;
+
+ master->mode_bits = SPI_MODE_3;
+ master->num_chipselect = 1;
+ master->bus_num = 0;
+
+ master->setup = falcon_spi_setup;
+ master->transfer = falcon_spi_transfer;
+ master->cleanup = falcon_spi_cleanup;
+
+ platform_set_drvdata(pdev, priv);
+
+ ret = spi_register_master(master);
+ if (ret)
+ goto unmap_sys1;
+
+ return 0;
+
+unmap_sys1:
+ iounmap(priv->sys1_membase);
+
+unmap_ebu:
+ iounmap(priv->ebu_membase);
+
+free_master:
+ spi_master_put(master);
+
+ return ret;
+}
+
+static int __devexit falcon_spi_remove(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct falcon_spi *priv = platform_get_drvdata(pdev);
+
+ dev_dbg(dev, "removed\n");
+
+ spi_unregister_master(priv->master);
+
+ iounmap(priv->sys1_membase);
+ iounmap(priv->ebu_membase);
+
+ return 0;
+}
+
+static struct platform_driver falcon_spi_driver = {
+ .probe = falcon_spi_probe,
+ .remove = __devexit_p(falcon_spi_remove),
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE
+ }
+};
+
+static int __init falcon_spi_init(void)
+{
+ return platform_driver_register(&falcon_spi_driver);
+}
+
+static void __exit falcon_spi_exit(void)
+{
+ platform_driver_unregister(&falcon_spi_driver);
+}
+
+module_init(falcon_spi_init);
+module_exit(falcon_spi_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Lantiq Falcon SPI controller driver");
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -210,6 +210,10 @@ config SPI_MPC52xx
This drivers supports the MPC52xx SPI controller in master SPI
mode.
+config SPI_FALCON
+ tristate "Falcon SPI controller support"
+ depends on SOC_FALCON
+
config SPI_MPC52xx_PSC
tristate "Freescale MPC52xx PSC SPI controller"
depends on PPC_MPC52xx && EXPERIMENTAL

View File

@ -1,193 +0,0 @@
--- a/arch/mips/lantiq/falcon/Makefile
+++ b/arch/mips/lantiq/falcon/Makefile
@@ -2,3 +2,4 @@ obj-y := clk-falcon.o devices.o gpio.o p
obj-y += softdog_vpe.o
obj-$(CONFIG_LANTIQ_MACH_EASY98000) += addon-easy98000.o
obj-$(CONFIG_LANTIQ_MACH_EASY98000) += mach-easy98000.o
+obj-$(CONFIG_LANTIQ_MACH_EASY98000) += dev-leds-easy98000-cpld.o
--- /dev/null
+++ b/arch/mips/lantiq/falcon/dev-leds-easy98000-cpld.c
@@ -0,0 +1,160 @@
+/*
+ * EASY98000 CPLD LED driver
+ *
+ * Copyright (C) 2010 Ralph Hempel <ralph.hempel@lantiq.com>
+ *
+ * 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <linux/leds.h>
+#include <linux/slab.h>
+
+#include "dev-leds-easy98000-cpld.h"
+
+const char *led_name[8] = {
+ "ge0_act",
+ "ge0_link",
+ "ge1_act",
+ "ge1_link",
+ "fe2_act",
+ "fe2_link",
+ "fe3_act",
+ "fe3_link"
+};
+
+#define cpld_base7 ((u16 *)(KSEG1 | 0x17c0000c))
+#define cpld_base8 ((u16 *)(KSEG1 | 0x17c00012))
+
+#define ltq_r16(reg) __raw_readw(reg)
+#define ltq_w16(val, reg) __raw_writew(val, reg)
+
+struct cpld_led_dev {
+ struct led_classdev cdev;
+ u8 mask;
+ u16 *base;
+};
+
+struct cpld_led_drvdata {
+ struct cpld_led_dev *led_devs;
+ int num_leds;
+};
+
+void led_set(u8 mask, u16 *base)
+{
+ ltq_w16(ltq_r16(base) | mask, base);
+}
+
+void led_clear(u8 mask, u16 *base)
+{
+ ltq_w16(ltq_r16(base) & (~mask), base);
+}
+
+void led_blink_clear(u8 mask, u16 *base)
+{
+ led_clear(mask, base);
+}
+
+static void led_brightness(struct led_classdev *led_cdev,
+ enum led_brightness value)
+{
+ struct cpld_led_dev *led_dev =
+ container_of(led_cdev, struct cpld_led_dev, cdev);
+
+ if (value)
+ led_set(led_dev->mask, led_dev->base);
+ else
+ led_clear(led_dev->mask, led_dev->base);
+}
+
+static int led_probe(struct platform_device *pdev)
+{
+ int i;
+ char name[32];
+ struct cpld_led_drvdata *drvdata;
+ int ret = 0;
+
+ drvdata = kzalloc(sizeof(struct cpld_led_drvdata) +
+ sizeof(struct cpld_led_dev) * MAX_LED,
+ GFP_KERNEL);
+ if (!drvdata)
+ return -ENOMEM;
+
+ drvdata->led_devs = (struct cpld_led_dev *) &drvdata[1];
+
+ for (i = 0; i < MAX_LED; i++) {
+ struct cpld_led_dev *led_dev = &drvdata->led_devs[i];
+ led_dev->cdev.brightness_set = led_brightness;
+ led_dev->cdev.default_trigger = NULL;
+ led_dev->mask = 1 << (i % 8);
+ if(i < 8) {
+ sprintf(name, "easy98000-cpld:%s", led_name[i]);
+ led_dev->base = cpld_base8;
+ } else {
+ sprintf(name, "easy98000-cpld:red:%d", i-8);
+ led_dev->base = cpld_base7;
+ }
+ led_dev->cdev.name = name;
+ ret = led_classdev_register(&pdev->dev, &led_dev->cdev);
+ if (ret)
+ goto err;
+ }
+ platform_set_drvdata(pdev, drvdata);
+ return 0;
+
+err:
+ printk("led_probe: 3\n");
+ for (i = i - 1; i >= 0; i--)
+ led_classdev_unregister(&drvdata->led_devs[i].cdev);
+
+ kfree(drvdata);
+ return ret;
+}
+
+static int led_remove(struct platform_device *pdev)
+{
+ int i;
+ struct cpld_led_drvdata *drvdata = platform_get_drvdata(pdev);
+ for (i = 0; i < MAX_LED; i++)
+ led_classdev_unregister(&drvdata->led_devs[i].cdev);
+ kfree(drvdata);
+ return 0;
+}
+
+static struct platform_driver led_driver = {
+ .probe = led_probe,
+ .remove = __devexit_p(led_remove),
+ .driver = {
+ .name = LED_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+int __init easy98000_cpld_led_init(void)
+{
+ pr_info(LED_DESC ", Version " LED_VERSION
+ " (c) Copyright 2011, Lantiq Deutschland GmbH\n");
+ return platform_driver_register(&led_driver);
+}
+
+void __exit easy98000_cpld_led_exit(void)
+{
+ platform_driver_unregister(&led_driver);
+}
+
+module_init(easy98000_cpld_led_init);
+module_exit(easy98000_cpld_led_exit);
+
+MODULE_DESCRIPTION(LED_NAME);
+MODULE_DESCRIPTION(LED_DESC);
+MODULE_AUTHOR("Ralph Hempel <ralph.hempel@lantiq.com>");
+MODULE_LICENSE("GPL v2");
+
--- /dev/null
+++ b/arch/mips/lantiq/falcon/dev-leds-easy98000-cpld.h
@@ -0,0 +1,20 @@
+/*
+ * EASY98000 CPLD LED driver
+ *
+ * Copyright (C) 2010 Ralph Hempel <ralph.hempel@lantiq.com>
+ *
+ * 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.
+ *
+ */
+#ifndef _INCLUDE_EASY98000_CPLD_LED_H_
+#define _INCLUDE_EASY98000_CPLD_LED_H_
+
+#define LED_NAME "easy98000_cpld_led"
+#define LED_DESC "EASY98000 LED driver"
+#define LED_VERSION "1.0.0"
+
+#define MAX_LED 16
+
+#endif /* _INCLUDE_EASY98000_CPLD_LED_H_ */

View File

@ -1,140 +0,0 @@
--- /dev/null
+++ b/arch/mips/lantiq/falcon/mach-easy98020.c
@@ -0,0 +1,117 @@
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/gpio.h>
+#include <linux/gpio_buttons.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
+#include "../machtypes.h"
+
+#include "devices.h"
+#include "dev-leds-gpio.h"
+
+#define EASY98020_GPIO_LED_0 9
+#define EASY98020_GPIO_LED_1 10
+#define EASY98020_GPIO_LED_2 11
+#define EASY98020_GPIO_LED_3 12
+#define EASY98020_GPIO_LED_GE0_ACT 110
+#define EASY98020_GPIO_LED_GE0_LINK 109
+#define EASY98020_GPIO_LED_GE1_ACT 106
+#define EASY98020_GPIO_LED_GE1_LINK 105
+
+extern unsigned char ltq_ethaddr[6];
+
+#ifdef CONFIG_MTD_PARTITIONS
+static struct mtd_partition easy98020_spi_partitions[] =
+{
+ {
+ .name = "uboot",
+ .offset = 0x0,
+ .size = 0x40000,
+ },
+ {
+ .name = "uboot_env",
+ .offset = 0x40000,
+ .size = 0x40000, /* 2 sectors for redundant env. */
+ },
+ {
+ .name = "linux",
+ .offset = 0x80000,
+ .size = 0xF80000, /* map only 16 MiB */
+ },
+};
+
+static struct flash_platform_data easy98020_spi_flash_platform_data = {
+ .name = "sflash",
+ .parts = easy98020_spi_partitions,
+ .nr_parts = ARRAY_SIZE(easy98020_spi_partitions)
+};
+#endif
+
+static struct spi_board_info easy98020_spi_flash_data __initdata = {
+ .modalias = "m25p80",
+ .bus_num = 0,
+ .chip_select = 0,
+ .max_speed_hz = 10 * 1000 * 1000,
+ .mode = SPI_MODE_3,
+#ifdef CONFIG_MTD_PARTITIONS
+ .platform_data = &easy98020_spi_flash_platform_data
+#endif
+};
+
+static struct gpio_led easy98020_leds_gpio[] __initdata = {
+ {
+ .name = "easy98020:green:0",
+ .gpio = EASY98020_GPIO_LED_0,
+ .active_low = 0,
+ }, {
+ .name = "easy98020:green:1",
+ .gpio = EASY98020_GPIO_LED_1,
+ .active_low = 0,
+ }, {
+ .name = "easy98020:green:2",
+ .gpio = EASY98020_GPIO_LED_2,
+ .active_low = 0,
+ }, {
+ .name = "easy98020:green:3",
+ .gpio = EASY98020_GPIO_LED_3,
+ .active_low = 0,
+ }, {
+ .name = "easy98020:ge0_act",
+ .gpio = EASY98020_GPIO_LED_GE0_ACT,
+ .active_low = 0,
+ }, {
+ .name = "easy98020:ge0_link",
+ .gpio = EASY98020_GPIO_LED_GE0_LINK,
+ .active_low = 0,
+ }, {
+ .name = "easy98020:ge1_act",
+ .gpio = EASY98020_GPIO_LED_GE1_ACT,
+ .active_low = 0,
+ }, {
+ .name = "easy98020:ge1_link",
+ .gpio = EASY98020_GPIO_LED_GE1_LINK,
+ .active_low = 0,
+ }
+};
+
+static void __init easy98020_init(void)
+{
+ falcon_register_asc(0);
+ falcon_register_gpio();
+ falcon_register_wdt();
+ falcon_register_i2c();
+ falcon_register_spi_flash(&easy98020_spi_flash_data);
+ ltq_add_device_leds_gpio(-1, ARRAY_SIZE(easy98020_leds_gpio),
+ easy98020_leds_gpio);
+ falcon_register_crypto();
+}
+
+MIPS_MACHINE(LANTIQ_MACH_EASY98020,
+ "EASY98020",
+ "EASY98020 Eval Board",
+ easy98020_init);
--- a/arch/mips/lantiq/falcon/Kconfig
+++ b/arch/mips/lantiq/falcon/Kconfig
@@ -6,6 +6,10 @@ config LANTIQ_MACH_EASY98000
bool "Easy98000"
default y
+config LANTIQ_MACH_EASY98020
+ bool "Easy98020"
+ default y
+
endmenu
endif
--- a/arch/mips/lantiq/falcon/Makefile
+++ b/arch/mips/lantiq/falcon/Makefile
@@ -3,3 +3,4 @@ obj-y += softdog_vpe.o
obj-$(CONFIG_LANTIQ_MACH_EASY98000) += addon-easy98000.o
obj-$(CONFIG_LANTIQ_MACH_EASY98000) += mach-easy98000.o
obj-$(CONFIG_LANTIQ_MACH_EASY98000) += dev-leds-easy98000-cpld.o
+obj-$(CONFIG_LANTIQ_MACH_EASY98020) += mach-easy98020.o

View File

@ -1,136 +0,0 @@
--- /dev/null
+++ b/arch/mips/lantiq/falcon/mach-95C3AM1.c
@@ -0,0 +1,103 @@
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/i2c-gpio.h>
+#include "../machtypes.h"
+
+#include "devices.h"
+#include "dev-leds-gpio.h"
+
+#define BOARD_95C3AM1_GPIO_LED_0 10
+#define BOARD_95C3AM1_GPIO_LED_1 11
+#define BOARD_95C3AM1_GPIO_LED_2 12
+#define BOARD_95C3AM1_GPIO_LED_3 13
+
+extern unsigned char ltq_ethaddr[6];
+
+#ifdef CONFIG_MTD_PARTITIONS
+static struct mtd_partition board_95C3AM1_partitions[] =
+{
+ {
+ .name = "uboot",
+ .offset = 0x0,
+ .size = 0x40000,
+ },
+ {
+ .name = "uboot_env",
+ .offset = 0x40000,
+ .size = 0x40000, /* 2 sectors for redundant env. */
+ },
+ {
+ .name = "linux",
+ .offset = 0x80000,
+ .size = 0xF80000, /* map only 16 MiB */
+ },
+};
+
+static struct flash_platform_data board_95C3AM1_flash_platform_data = {
+ .name = "sflash",
+ .parts = board_95C3AM1_partitions,
+ .nr_parts = ARRAY_SIZE(board_95C3AM1_partitions)
+};
+#endif
+
+static struct spi_board_info board_95C3AM1_flash_data __initdata = {
+ .modalias = "m25p80",
+ .bus_num = 0,
+ .chip_select = 0,
+ .max_speed_hz = 10 * 1000 * 1000,
+ .mode = SPI_MODE_3,
+#ifdef CONFIG_MTD_PARTITIONS
+ .platform_data = &board_95C3AM1_flash_platform_data
+#endif
+};
+
+static struct gpio_led board_95C3AM1_leds_gpio[] __initdata = {
+ {
+ .name = "power",
+ .gpio = BOARD_95C3AM1_GPIO_LED_0,
+ .active_low = 0,
+ }, {
+ .name = "optical",
+ .gpio = BOARD_95C3AM1_GPIO_LED_1,
+ .active_low = 0,
+ }, {
+ .name = "lan",
+ .gpio = BOARD_95C3AM1_GPIO_LED_2,
+ .active_low = 0,
+ }, {
+ .name = "update",
+ .gpio = BOARD_95C3AM1_GPIO_LED_3,
+ .active_low = 0,
+ }
+};
+
+static struct i2c_gpio_platform_data board_95C3AM1_i2c_gpio_data = {
+ .sda_pin = 107,
+ .scl_pin = 108,
+};
+
+static struct platform_device board_95C3AM1_i2c_gpio_device = {
+ .name = "i2c-gpio",
+ .id = 0,
+ .dev = {
+ .platform_data = &board_95C3AM1_i2c_gpio_data,
+ }
+};
+
+static void __init board_95C3AM1_init(void)
+{
+ falcon_register_asc(0);
+ falcon_register_gpio();
+ falcon_register_wdt();
+ falcon_register_i2c();
+ falcon_register_spi_flash(&board_95C3AM1_flash_data);
+ platform_device_register(&board_95C3AM1_i2c_gpio_device);
+ ltq_add_device_leds_gpio(-1, ARRAY_SIZE(board_95C3AM1_leds_gpio),
+ board_95C3AM1_leds_gpio);
+ falcon_register_crypto();
+}
+
+MIPS_MACHINE(LANTIQ_MACH_95C3AM1,
+ "95C3AM1",
+ "95C3AM1 Board",
+ board_95C3AM1_init);
--- a/arch/mips/lantiq/falcon/Kconfig
+++ b/arch/mips/lantiq/falcon/Kconfig
@@ -10,6 +10,10 @@ config LANTIQ_MACH_EASY98020
bool "Easy98020"
default y
+config LANTIQ_MACH_95C3AM1
+ bool "95C3AM1"
+ default y
+
endmenu
endif
--- a/arch/mips/lantiq/falcon/Makefile
+++ b/arch/mips/lantiq/falcon/Makefile
@@ -4,3 +4,4 @@ obj-$(CONFIG_LANTIQ_MACH_EASY98000) += a
obj-$(CONFIG_LANTIQ_MACH_EASY98000) += mach-easy98000.o
obj-$(CONFIG_LANTIQ_MACH_EASY98000) += dev-leds-easy98000-cpld.o
obj-$(CONFIG_LANTIQ_MACH_EASY98020) += mach-easy98020.o
+obj-$(CONFIG_LANTIQ_MACH_95C3AM1) += mach-95C3AM1.o
--- a/arch/mips/lantiq/machtypes.h
+++ b/arch/mips/lantiq/machtypes.h
@@ -21,6 +21,7 @@ enum lantiq_mach_type {
LANTIQ_MACH_EASY98000SF, /* Falcon Eval Board, Serial Flash */
LANTIQ_MACH_EASY98000NAND, /* Falcon Eval Board, NAND Flash */
LANTIQ_MACH_EASY98020, /* Falcon Reference Board */
+ LANTIQ_MACH_95C3AM1, /* Board 95C3AM1 */
};
#endif

View File

@ -1,678 +0,0 @@
--- a/arch/mips/lantiq/xway/Kconfig
+++ b/arch/mips/lantiq/xway/Kconfig
@@ -6,6 +6,10 @@
bool "Easy50712 - Danube"
default y
+config LANTIQ_MACH_ARV45XX
+ bool "ARV45XX"
+ default y
+
endmenu
endif
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -5,3 +5,4 @@
obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o
obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o
+obj-$(CONFIG_LANTIQ_MACH_ARV45XX) += mach-arv45xx.o
--- /dev/null
+++ b/arch/mips/lantiq/xway/mach-arv45xx.c
@@ -0,0 +1,634 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/gpio.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/input.h>
+#include <linux/etherdevice.h>
+#include <linux/ath5k_platform.h>
+#include <linux/pci.h>
+
+#include <lantiq_soc.h>
+#include <lantiq_platform.h>
+
+#include "../machtypes.h"
+#include "devices.h"
+#include "dev-leds-gpio.h"
+#include "dev-dwc_otg.h"
+#include "../dev-gpio-buttons.h"
+
+#ifdef CONFIG_MTD_PARTITIONS
+static struct mtd_partition arv4510_partitions[] =
+{
+ {
+ .name = "uboot",
+ .offset = 0x0,
+ .size = 0x20000,
+ },
+ {
+ .name = "uboot_env",
+ .offset = 0x20000,
+ .size = 0x120000,
+ },
+ {
+ .name = "linux",
+ .offset = 0x40000,
+ .size = 0xfa0000,
+ },
+ {
+ .name = "board_config",
+ .offset = 0xfe0000,
+ .size = 0x20000,
+ },
+};
+
+static struct mtd_partition arv45xx_partitions[] =
+{
+ {
+ .name = "uboot",
+ .offset = 0x0,
+ .size = 0x20000,
+ },
+ {
+ .name = "uboot_env",
+ .offset = 0x20000,
+ .size = 0x10000,
+ },
+ {
+ .name = "linux",
+ .offset = 0x30000,
+ .size = 0x3c0000,
+ },
+ {
+ .name = "board_config",
+ .offset = 0x3f0000,
+ .size = 0x10000,
+ },
+};
+
+static struct mtd_partition arv75xx_partitions[] =
+{
+ {
+ .name = "uboot",
+ .offset = 0x0,
+ .size = 0x10000,
+ },
+ {
+ .name = "uboot_env",
+ .offset = 0x10000,
+ .size = 0x10000,
+ },
+ {
+ .name = "linux",
+ .offset = 0x20000,
+ .size = 0x7d0000,
+ },
+ {
+ .name = "board_config",
+ .offset = 0x7f0000,
+ .size = 0x10000,
+ },
+};
+
+static struct mtd_partition arv7525_partitions[] =
+{
+ {
+ .name = "uboot",
+ .offset = 0x0,
+ .size = 0x10000,
+ },
+ {
+ .name = "uboot_env",
+ .offset = 0x10000,
+ .size = 0x10000,
+ },
+ {
+ .name = "linux",
+ .offset = 0x20000,
+ .size = 0x3d0000,
+ },
+ {
+ .name = "board_config",
+ .offset = 0x3f0000,
+ .size = 0x10000,
+ },
+};
+#endif
+
+static struct physmap_flash_data arv4510_flash_data = {
+#ifdef CONFIG_MTD_PARTITIONS
+ .nr_parts = ARRAY_SIZE(arv4510_partitions),
+ .parts = arv4510_partitions,
+#endif
+};
+
+static struct physmap_flash_data arv45xx_flash_data = {
+#ifdef CONFIG_MTD_PARTITIONS
+ .nr_parts = ARRAY_SIZE(arv45xx_partitions),
+ .parts = arv45xx_partitions,
+#endif
+};
+
+static struct physmap_flash_data arv75xx_flash_data = {
+#ifdef CONFIG_MTD_PARTITIONS
+ .nr_parts = ARRAY_SIZE(arv75xx_partitions),
+ .parts = arv75xx_partitions,
+#endif
+};
+
+static struct physmap_flash_data arv7525_flash_data = {
+#ifdef CONFIG_MTD_PARTITIONS
+ .nr_parts = ARRAY_SIZE(arv7525_partitions),
+ .parts = arv7525_partitions,
+#endif
+};
+
+static struct ltq_pci_data ltq_pci_data = {
+ .clock = PCI_CLOCK_EXT,
+ .gpio = PCI_GNT1 | PCI_REQ1,
+ .irq = {
+ [14] = INT_NUM_IM0_IRL0 + 22,
+ },
+};
+
+static struct ltq_eth_data ltq_eth_data = {
+ .mii_mode = PHY_INTERFACE_MODE_RMII,
+};
+
+static struct gpio_led
+arv4510pw_leds_gpio[] __initdata = {
+ { .name = "soc:green:foo", .gpio = 4, .active_low = 1, },
+};
+
+static struct gpio_led
+arv4518pw_leds_gpio[] __initdata = {
+ { .name = "soc:green:power", .gpio = 3, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:green:adsl", .gpio = 4, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:green:internet", .gpio = 5, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:green:wlan", .gpio = 6, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:yellow:wps", .gpio = 7, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:red:fail", .gpio = 8, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:green:usb", .gpio = 19, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:green:voip", .gpio = 72, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:green:fxs1", .gpio = 73, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:green:fxs2", .gpio = 74, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:green:fxo", .gpio = 75, .active_low = 1, .default_trigger = "default-on" },
+};
+
+static struct gpio_keys_button
+arv4518pw_gpio_keys[] __initdata = {
+ {
+ .desc = "wlan",
+ .type = EV_KEY,
+ .code = BTN_0,
+ .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
+ .gpio = 28,
+ .active_low = 1,
+ },
+ {
+ .desc = "wps",
+ .type = EV_KEY,
+ .code = BTN_1,
+ .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
+ .gpio = 29,
+ .active_low = 1,
+ },
+ {
+ .desc = "reset",
+ .type = EV_KEY,
+ .code = BTN_2,
+ .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
+ .gpio = 30,
+ .active_low = 1,
+ },
+};
+
+static struct gpio_led
+arv4520pw_leds_gpio[] __initdata = {
+ { .name = "soc:blue:power", .gpio = 3, .active_low = 1, },
+ { .name = "soc:blue:adsl", .gpio = 4, .active_low = 1, },
+ { .name = "soc:blue:internet", .gpio = 5, .active_low = 1, },
+ { .name = "soc:red:power", .gpio = 6, .active_low = 1, },
+ { .name = "soc:yellow:wps", .gpio = 7, .active_low = 1, },
+ { .name = "soc:red:wps", .gpio = 9, .active_low = 1, },
+ { .name = "soc:blue:voip", .gpio = 72, .active_low = 1, },
+ { .name = "soc:blue:fxs1", .gpio = 73, .active_low = 1, },
+ { .name = "soc:blue:fxs2", .gpio = 74, .active_low = 1, },
+ { .name = "soc:blue:fxo", .gpio = 75, .active_low = 1, },
+ { .name = "soc:blue:voice", .gpio = 76, .active_low = 1, },
+ { .name = "soc:blue:usb", .gpio = 77, .active_low = 1, },
+ { .name = "soc:blue:wlan", .gpio = 78, .active_low = 1, },
+};
+
+static struct gpio_led
+arv452cpw_leds_gpio[] __initdata = {
+ { .name = "soc:blue:power", .gpio = 3, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:blue:adsl", .gpio = 4, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:blue:isdn", .gpio = 5, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:red:power", .gpio = 6, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:yellow:wps", .gpio = 7, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:red:wps", .gpio = 9, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:blue:fxs1", .gpio = 72, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:blue:fxs2", .gpio = 73, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:blue:wps", .gpio = 74, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:blue:fxo", .gpio = 75, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:blue:voice", .gpio = 76, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:blue:usb", .gpio = 77, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:blue:wlan", .gpio = 78, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:blue:internet", .gpio = 80, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:red:internet", .gpio = 81, .active_low = 1, .default_trigger = "default-on" },
+};
+
+static struct gpio_led
+arv4525pw_leds_gpio[] __initdata = {
+ { .name = "soc:green:festnetz", .gpio = 4, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:green:internet", .gpio = 5, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:green:dsl", .gpio = 6, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:green:wlan", .gpio = 8, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:green:online", .gpio = 9, .active_low = 1, .default_trigger = "default-on" },
+};
+
+static struct gpio_led
+arv752dpw22_leds_gpio[] __initdata = {
+ { .name = "soc:blue:power", .gpio = 3, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:red:internet", .gpio = 5, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:red:power", .gpio = 6, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:red:wps", .gpio = 8, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:red:fxo", .gpio = 75, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:red:voice", .gpio = 76, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:green:usb", .gpio = 77, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:green:wlan", .gpio = 78, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:green:wlan1", .gpio = 79, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:blue:wlan", .gpio = 80, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:blue:wlan1", .gpio = 81, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:green:eth1", .gpio = 83, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:green:eth2", .gpio = 84, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:green:eth3", .gpio = 85, .active_low = 1, .default_trigger = "default-on" },
+ { .name = "soc:green:eth4", .gpio = 86, .active_low = 1, .default_trigger = "default-on", },
+};
+
+static struct gpio_keys_button
+arv752dpw22_gpio_keys[] __initdata = {
+ {
+ .desc = "btn0",
+ .type = EV_KEY,
+ .code = BTN_0,
+ .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
+ .gpio = 12,
+ .active_low = 1,
+ },
+ {
+ .desc = "btn1",
+ .type = EV_KEY,
+ .code = BTN_1,
+ .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
+ .gpio = 13,
+ .active_low = 1,
+ },
+ {
+ .desc = "btn2",
+ .type = EV_KEY,
+ .code = BTN_2,
+ .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
+ .gpio = 28,
+ .active_low = 1,
+ },
+};
+
+static struct gpio_led
+arv7518pw_leds_gpio[] __initdata = {
+ { .name = "soc:green:power", .gpio = 2, .active_low = 1, },
+ { .name = "soc:green:adsl", .gpio = 4, .active_low = 1, },
+ { .name = "soc:green:internet", .gpio = 5, .active_low = 1, },
+ { .name = "soc:green:wlan", .gpio = 6, .active_low = 1, },
+ { .name = "soc:red:internet", .gpio = 8, .active_low = 1, },
+ { .name = "soc:green:usb", .gpio = 19, .active_low = 1, },
+};
+
+static struct gpio_keys_button
+arv7518pw_gpio_keys[] __initdata = {
+ {
+ .desc = "reset",
+ .type = EV_KEY,
+ .code = BTN_0,
+ .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
+ .gpio = 23,
+ .active_low = 1,
+ },
+ {
+ .desc = "wlan",
+ .type = EV_KEY,
+ .code = BTN_1,
+ .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
+ .gpio = 25,
+ .active_low = 1,
+ },
+};
+
+static void
+arv45xx_register_ethernet(void)
+{
+#define ARV45XX_BRN_MAC 0x3f0016
+ memcpy_fromio(&ltq_eth_data.mac.sa_data,
+ (void *)KSEG1ADDR(LTQ_FLASH_START + ARV45XX_BRN_MAC), 6);
+ ltq_register_etop(&ltq_eth_data);
+}
+
+static void
+arv75xx_register_ethernet(void)
+{
+#define ARV75XX_BRN_MAC 0x7f0016
+ memcpy_fromio(&ltq_eth_data.mac.sa_data,
+ (void *)KSEG1ADDR(LTQ_FLASH_START + ARV75XX_BRN_MAC), 6);
+ ltq_register_etop(&ltq_eth_data);
+}
+
+static void
+bewan_register_ethernet(void)
+{
+#define BEWAN_BRN_MAC 0x3f0014
+ memcpy_fromio(&ltq_eth_data.mac.sa_data,
+ (void *)KSEG1ADDR(LTQ_FLASH_START + BEWAN_BRN_MAC), 6);
+ ltq_register_etop(&ltq_eth_data);
+}
+
+static u16 arv45xx_ath5k_eeprom_data[ATH5K_PLAT_EEP_MAX_WORDS];
+static struct ath5k_platform_data arv45xx_ath5k_platform_data;
+
+/*static int arv45xx_pci_plat_dev_init(struct pci_dev *dev)
+{
+ dev->dev.platform_data = &arv45xx_ath5k_platform_data;
+ return 0;
+}
+*/
+void __init
+arv45xx_register_ath5k(void)
+{
+#define ARV45XX_BRN_ATH 0x3f0478
+ int i;
+ unsigned char eeprom_mac[6];
+ static u16 eeprom_data[ATH5K_PLAT_EEP_MAX_WORDS];
+ u32 *p = (u32*)arv45xx_ath5k_eeprom_data;
+
+ memcpy_fromio(eeprom_mac,
+ (void *)KSEG1ADDR(LTQ_FLASH_START + ARV45XX_BRN_MAC), 6);
+ eeprom_mac[5]++;
+ memcpy_fromio(arv45xx_ath5k_eeprom_data,
+ (void *)KSEG1ADDR(LTQ_FLASH_START + ARV45XX_BRN_ATH), ATH5K_PLAT_EEP_MAX_WORDS);
+ // swap eeprom bytes
+ for (i = 0; i < ATH5K_PLAT_EEP_MAX_WORDS>>1; i++){
+ //arv4518_ath5k_eeprom_data[i] = ((eeprom_data[i]&0xff)<<8)|((eeprom_data[i]&0xff00)>>8);
+ p[i] = ((eeprom_data[(i<<1)+1]&0xff)<<24)|((eeprom_data[(i<<1)+1]&0xff00)<<8)|((eeprom_data[i<<1]&0xff)<<8)|((eeprom_data[i<<1]&0xff00)>>8);
+ if (i == 0xbf>>1){
+ // printk ("regdomain: 0x%x --> 0x%x\n", p[i], (p[i] & 0xffff0000)|0x67);
+ /* regdomain is invalid?? how did original fw convert
+ * value to 0x82d4 ??
+ * for now, force to 0x67 */
+ p[i] &= 0xffff0000;
+ p[i] |= 0x67;
+ }
+ }
+ arv45xx_ath5k_platform_data.eeprom_data = arv45xx_ath5k_eeprom_data;
+ arv45xx_ath5k_platform_data.macaddr = eeprom_mac;
+ //lqpci_plat_dev_init = arv45xx_pci_plat_dev_init;
+}
+
+static void __init
+arv3527p_init(void)
+{
+ ltq_register_gpio_stp();
+ //ltq_add_device_leds_gpio(arv3527p_leds_gpio, ARRAY_SIZE(arv3527p_leds_gpio));
+ ltq_register_nor(&arv45xx_flash_data);
+ arv45xx_register_ethernet();
+}
+
+MIPS_MACHINE(LANTIQ_MACH_ARV3527P,
+ "ARV3527P",
+ "ARV3527P - Arcor Easybox 401",
+ arv3527p_init);
+
+static void __init
+arv4510pw_init(void)
+{
+ ltq_register_gpio_stp();
+ ltq_add_device_leds_gpio(-1, ARRAY_SIZE(arv4510pw_leds_gpio), arv4510pw_leds_gpio);
+ ltq_register_nor(&arv4510_flash_data);
+ ltq_pci_data.irq[12] = (INT_NUM_IM2_IRL0 + 31);
+ ltq_pci_data.irq[15] = (INT_NUM_IM0_IRL0 + 26);
+ ltq_pci_data.gpio |= PCI_EXIN2 | PCI_REQ2;
+ ltq_register_pci(&ltq_pci_data);
+ bewan_register_ethernet();
+}
+
+MIPS_MACHINE(LANTIQ_MACH_ARV4510PW,
+ "ARV4510PW",
+ "ARV4510PW - Wippies Homebox",
+ arv4510pw_init);
+
+static void __init
+arv4518pw_init(void)
+{
+#define ARV4518PW_EBU 0
+#define ARV4518PW_USB 14
+#define ARV4518PW_SWITCH_RESET 13
+#define ARV4518PW_MADWIFI_ADDR 0xb07f0400
+
+ ltq_register_gpio_ebu(ARV4518PW_EBU);
+ ltq_add_device_leds_gpio(-1, ARRAY_SIZE(arv4518pw_leds_gpio), arv4518pw_leds_gpio);
+ ltq_register_gpio_keys_polled(-1, LTQ_KEYS_POLL_INTERVAL, ARRAY_SIZE(arv4518pw_gpio_keys), arv4518pw_gpio_keys);
+ ltq_register_nor(&arv45xx_flash_data);
+ ltq_pci_data.gpio = PCI_GNT2 | PCI_REQ2;
+ ltq_register_pci(&ltq_pci_data);
+ ltq_register_madwifi_eep(ARV4518PW_MADWIFI_ADDR);
+ xway_register_dwc(ARV4518PW_USB);
+ arv45xx_register_ethernet();
+ arv45xx_register_ath5k();
+
+ gpio_request(ARV4518PW_SWITCH_RESET, "switch");
+ gpio_direction_output(ARV4518PW_SWITCH_RESET, 1);
+ gpio_export(ARV4518PW_SWITCH_RESET, 0);
+}
+
+MIPS_MACHINE(LANTIQ_MACH_ARV4518PW,
+ "ARV4518PW",
+ "ARV4518PW - SMC7908A-ISP, Airties WAV-221",
+ arv4518pw_init);
+
+static void __init
+arv4520pw_init(void)
+{
+#define ARV4520PW_EBU 0x400
+#define ARV4520PW_USB 28
+#define ARV4520PW_SWITCH_RESET 82
+
+ ltq_register_gpio_ebu(ARV4520PW_EBU);
+ ltq_add_device_leds_gpio(-1, ARRAY_SIZE(arv4520pw_leds_gpio), arv4520pw_leds_gpio);
+ ltq_register_nor(&arv45xx_flash_data);
+ ltq_register_pci(&ltq_pci_data);
+ ltq_register_tapi();
+ arv45xx_register_ethernet();
+ xway_register_dwc(ARV4520PW_USB);
+
+ gpio_request(ARV4520PW_SWITCH_RESET, "switch");
+ gpio_set_value(ARV4520PW_SWITCH_RESET, 1);
+}
+
+MIPS_MACHINE(LANTIQ_MACH_ARV4520PW,
+ "ARV4520PW",
+ "ARV4520PW - Airties WAV-281, Arcor A800",
+ arv4520pw_init);
+
+static void __init
+arv452Cpw_init(void)
+{
+#define ARV452CPW_EBU 0x77f
+#define ARV452CPW_USB 28
+#define ARV452CPW_RELAY1 31
+#define ARV452CPW_RELAY2 79
+#define ARV452CPW_SWITCH_RESET 82
+#define ARV452CPW_MADWIFI_ADDR 0xb07f0400
+
+ ltq_register_gpio_ebu(ARV452CPW_EBU);
+ ltq_add_device_leds_gpio(-1, ARRAY_SIZE(arv452cpw_leds_gpio), arv452cpw_leds_gpio);
+ ltq_register_nor(&arv45xx_flash_data);
+ ltq_register_pci(&ltq_pci_data);
+ ltq_register_madwifi_eep(ARV452CPW_MADWIFI_ADDR);
+ xway_register_dwc(ARV452CPW_USB);
+ arv45xx_register_ethernet();
+ arv45xx_register_ath5k();
+
+ gpio_request(ARV452CPW_SWITCH_RESET, "switch");
+ gpio_set_value(ARV452CPW_SWITCH_RESET, 1);
+ gpio_export(ARV452CPW_SWITCH_RESET, 0);
+
+ gpio_request(ARV452CPW_RELAY1, "relay1");
+ gpio_direction_output(ARV452CPW_RELAY1, 1);
+ gpio_export(ARV452CPW_RELAY1, 0);
+
+ gpio_request(ARV452CPW_RELAY2, "relay2");
+ gpio_set_value(ARV452CPW_RELAY2, 1);
+ gpio_export(ARV452CPW_RELAY2, 0);
+}
+
+MIPS_MACHINE(LANTIQ_MACH_ARV452CPW,
+ "ARV452CPW",
+ "ARV452CPW - Arcor A801",
+ arv452Cpw_init);
+
+static void __init
+arv4525pw_init(void)
+{
+#define ARV4525PW_MADWIFI_ADDR 0xb07f0400
+
+ ltq_add_device_leds_gpio(-1, ARRAY_SIZE(arv4525pw_leds_gpio), arv4525pw_leds_gpio);
+ ltq_register_nor(&arv45xx_flash_data);
+ ltq_pci_data.clock = PCI_CLOCK_INT;
+ ltq_register_pci(&ltq_pci_data);
+ ltq_register_madwifi_eep(ARV4525PW_MADWIFI_ADDR);
+ ltq_eth_data.mii_mode = PHY_INTERFACE_MODE_MII;
+ arv45xx_register_ethernet();
+}
+
+MIPS_MACHINE(LANTIQ_MACH_ARV4525PW,
+ "ARV4525PW",
+ "ARV4525PW - Speedport W502V",
+ arv4525pw_init);
+
+static void __init
+arv7525pw_init(void)
+{
+ ltq_add_device_leds_gpio(-1, ARRAY_SIZE(arv4525pw_leds_gpio), arv4525pw_leds_gpio);
+ ltq_register_nor(&arv7525_flash_data);
+ ltq_register_pci(&ltq_pci_data);
+ ltq_eth_data.mii_mode = PHY_INTERFACE_MODE_MII;
+ ltq_register_tapi();
+ arv45xx_register_ethernet();
+}
+
+MIPS_MACHINE(LANTIQ_MACH_ARV7525PW,
+ "ARV7525PW",
+ "ARV7525PW - Speedport W303V",
+ arv7525pw_init);
+
+static void __init
+arv7518pw_init(void)
+{
+#define ARV7518PW_EBU 0x2
+#define ARV7518PW_USB 14
+
+ ltq_register_gpio_ebu(ARV7518PW_EBU);
+ ltq_add_device_leds_gpio(-1, ARRAY_SIZE(arv7518pw_leds_gpio), arv7518pw_leds_gpio);
+ ltq_register_gpio_keys_polled(-1, LTQ_KEYS_POLL_INTERVAL, ARRAY_SIZE(arv7518pw_gpio_keys), arv7518pw_gpio_keys);
+ ltq_register_nor(&arv75xx_flash_data);
+ ltq_register_pci(&ltq_pci_data);
+ ltq_register_tapi();
+ xway_register_dwc(ARV7518PW_USB);
+ arv75xx_register_ethernet();
+ //arv7518_register_ath9k(mac);
+}
+
+MIPS_MACHINE(LANTIQ_MACH_ARV7518PW,
+ "ARV7518PW",
+ "ARV7518PW - ASTORIA",
+ arv7518pw_init);
+
+
+static void __init
+arv752dpw_init(void)
+{
+#define ARV752DPW22_EBU 0x2
+#define ARV752DPW22_USB 72
+#define ARV752DPW22_RELAY 73
+ ltq_register_gpio_ebu(ARV752DPW22_EBU);
+ ltq_add_device_leds_gpio(-1, ARRAY_SIZE(arv752dpw22_leds_gpio), arv752dpw22_leds_gpio);
+ ltq_register_gpio_keys_polled(-1, LTQ_KEYS_POLL_INTERVAL, ARRAY_SIZE(arv752dpw22_gpio_keys), arv752dpw22_gpio_keys);
+ ltq_register_nor(&arv75xx_flash_data);
+ ltq_register_pci(&ltq_pci_data);
+ xway_register_dwc(ARV752DPW22_USB);
+ arv75xx_register_ethernet();
+ gpio_request(ARV752DPW22_RELAY, "relay");
+ gpio_set_value(ARV752DPW22_RELAY, 1);
+ gpio_export(ARV752DPW22_RELAY, 0);
+}
+
+MIPS_MACHINE(LANTIQ_MACH_ARV752DPW,
+ "ARV752DPW",
+ "ARV752DPW - Arcor A802",
+ arv752dpw_init);
+
+static void __init
+arv752dpw22_init(void)
+{
+#define ARV752DPW22_EBU 0x2
+#define ARV752DPW22_USB 72
+#define ARV752DPW22_RELAY 73
+
+ ltq_register_gpio_ebu(ARV752DPW22_EBU);
+ ltq_add_device_leds_gpio(-1, ARRAY_SIZE(arv752dpw22_leds_gpio), arv752dpw22_leds_gpio);
+ ltq_register_gpio_keys_polled(-1, LTQ_KEYS_POLL_INTERVAL, ARRAY_SIZE(arv752dpw22_gpio_keys), arv752dpw22_gpio_keys);
+ ltq_register_nor(&arv75xx_flash_data);
+ ltq_pci_data.irq[15] = (INT_NUM_IM3_IRL0 + 31);
+ ltq_pci_data.gpio |= PCI_EXIN1 | PCI_REQ2;
+ ltq_register_pci(&ltq_pci_data);
+ xway_register_dwc(ARV752DPW22_USB);
+ arv75xx_register_ethernet();
+
+ gpio_request(ARV752DPW22_RELAY, "relay");
+ gpio_set_value(ARV752DPW22_RELAY, 1);
+ gpio_export(ARV752DPW22_RELAY, 0);
+}
+
+MIPS_MACHINE(LANTIQ_MACH_ARV752DPW22,
+ "ARV752DPW22",
+ "ARV752DPW22 - Arcor A803",
+ arv752dpw22_init);
--- a/arch/mips/lantiq/machtypes.h
+++ b/arch/mips/lantiq/machtypes.h
@@ -22,6 +22,18 @@
LANTIQ_MACH_EASY98000NAND, /* Falcon Eval Board, NAND Flash */
LANTIQ_MACH_EASY98020, /* Falcon Reference Board */
LANTIQ_MACH_95C3AM1, /* Board 95C3AM1 */
+
+ /* Arcadyan */
+ LANTIQ_MACH_ARV3527P, /* Arcor easybox a401 */
+ LANTIQ_MACH_ARV4510PW, /* Wippies Homebox */
+ LANTIQ_MACH_ARV4518PW, /* Airties WAV-221, SMC-7908A-ISP */
+ LANTIQ_MACH_ARV4520PW, /* Airties WAV-281, Arcor EasyboxA800 */
+ LANTIQ_MACH_ARV452CPW, /* Arcor EasyboxA801 */
+ LANTIQ_MACH_ARV4525PW, /* Speedport W502V */
+ LANTIQ_MACH_ARV7525PW, /* Speedport W303V Typ A */
+ LANTIQ_MACH_ARV752DPW, /* Arcor easybox a802 */
+ LANTIQ_MACH_ARV752DPW22, /* Arcor easybox a803 */
+ LANTIQ_MACH_ARV7518PW, /* ASTORIA */
};
#endif

View File

@ -1,116 +0,0 @@
--- a/drivers/mtd/Kconfig
+++ b/drivers/mtd/Kconfig
@@ -57,6 +57,10 @@ config MTD_ROOTFS_SPLIT
depends on MTD_PARTITIONS
default y
+config MTD_UIMAGE_SPLIT
+ bool "Automatically split 'linux' partition into 'kernel' and 'rootfs'"
+ default y
+
config MTD_REDBOOT_PARTS
tristate "RedBoot partition table parsing"
---help---
--- a/drivers/mtd/mtdpart.c
+++ b/drivers/mtd/mtdpart.c
@@ -860,6 +860,82 @@ static int refresh_rootfs_split(struct m
}
#endif /* CONFIG_MTD_ROOTFS_SPLIT */
+
+#ifdef CONFIG_MTD_UIMAGE_SPLIT
+static unsigned long find_uimage_size(struct mtd_info *mtd,
+ unsigned long offset)
+{
+#define UBOOT_MAGIC 0x56190527
+ unsigned long magic = 0;
+ unsigned long temp;
+ size_t len;
+ int ret;
+
+ ret = mtd->read(mtd, offset, 4, &len, (void *)&magic);
+ if (ret || len != sizeof(magic))
+ return 0;
+
+ if (le32_to_cpu(magic) != UBOOT_MAGIC)
+ return 0;
+
+ ret = mtd->read(mtd, offset + 12, 4, &len, (void *)&temp);
+ if (ret || len != sizeof(temp))
+ return 0;
+
+ return temp + 0x40;
+}
+
+static int detect_squashfs_partition(struct mtd_info *mtd, unsigned long offset)
+{
+ unsigned long temp;
+ size_t len;
+ int ret;
+
+ ret = mtd->read(mtd, offset, 4, &len, (void *)&temp);
+ if (ret || len != sizeof(temp))
+ return 0;
+
+ return le32_to_cpu(temp) == SQUASHFS_MAGIC;
+}
+
+static int split_uimage(struct mtd_info *mtd,
+ const struct mtd_partition *part)
+{
+ static struct mtd_partition split_partitions[] = {
+ {
+ .name = "kernel",
+ .offset = 0x0,
+ .size = 0x0,
+ }, {
+ .name = "rootfs",
+ .offset = 0x0,
+ .size = 0x0,
+ },
+ };
+
+ split_partitions[0].size = find_uimage_size(mtd, part->offset);
+ if (!split_partitions[0].size) {
+ printk(KERN_NOTICE "no uImage found in linux partition\n");
+ return -1;
+ }
+
+ if (!detect_squashfs_partition(mtd,
+ part->offset
+ + split_partitions[0].size)) {
+ split_partitions[0].size &= ~(mtd->erasesize - 1);
+ split_partitions[0].size += mtd->erasesize;
+ }
+
+ split_partitions[0].offset = part->offset;
+ split_partitions[1].offset = part->offset + split_partitions[0].size;
+ split_partitions[1].size = part->size - split_partitions[0].size;
+
+ add_mtd_partitions(mtd, split_partitions, 2);
+
+ return 0;
+}
+#endif
+
/*
* This function, given a master MTD object and a partition table, creates
* and registers slave MTD objects which are bound to the master according to
@@ -893,6 +969,17 @@ int add_mtd_partitions(struct mtd_info *
add_mtd_device(&slave->mtd);
+#ifdef CONFIG_MTD_UIMAGE_SPLIT
+ if (!strcmp(parts[i].name, "linux")) {
+ ret = split_uimage(master, &parts[i]);
+
+ if (ret) {
+ printk(KERN_WARNING
+ "Can't split linux partition\n");
+ }
+ }
+#endif
+
if (!strcmp(parts[i].name, "rootfs")) {
#ifdef CONFIG_MTD_ROOTFS_ROOT_DEV
if (ROOT_DEV == 0) {

View File

@ -1,42 +0,0 @@
--- a/arch/mips/mm/cache.c
+++ b/arch/mips/mm/cache.c
@@ -52,6 +52,8 @@ void (*_dma_cache_wback)(unsigned long s
void (*_dma_cache_inv)(unsigned long start, unsigned long size);
EXPORT_SYMBOL(_dma_cache_wback_inv);
+EXPORT_SYMBOL(_dma_cache_wback);
+EXPORT_SYMBOL(_dma_cache_inv);
#endif /* CONFIG_DMA_NONCOHERENT */
--- a/net/atm/proc.c
+++ b/net/atm/proc.c
@@ -154,7 +154,7 @@ static void *vcc_seq_next(struct seq_fil
static void pvc_info(struct seq_file *seq, struct atm_vcc *vcc)
{
static const char *const class_name[] = {
- "off", "UBR", "CBR", "VBR", "ABR"};
+ "off","UBR","CBR","NTR-VBR","ABR","ANY","RT-VBR","UBR+","GFR"};
static const char *const aal_name[] = {
"---", "1", "2", "3/4", /* 0- 3 */
"???", "5", "???", "???", /* 4- 7 */
--- a/net/atm/common.c
+++ b/net/atm/common.c
@@ -62,11 +62,17 @@ static void vcc_remove_socket(struct soc
write_unlock_irq(&vcc_sklist_lock);
}
+struct sk_buff* (*ifx_atm_alloc_tx)(struct atm_vcc *, unsigned int) = NULL;
+EXPORT_SYMBOL(ifx_atm_alloc_tx);
+
static struct sk_buff *alloc_tx(struct atm_vcc *vcc, unsigned int size)
{
struct sk_buff *skb;
struct sock *sk = sk_atm(vcc);
+ if (ifx_atm_alloc_tx != NULL)
+ return ifx_atm_alloc_tx(vcc, size);
+
if (sk_wmem_alloc_get(sk) && !atm_may_send(vcc, size)) {
pr_debug("Sorry: wmem_alloc = %d, size = %d, sndbuf = %d\n",
sk_wmem_alloc_get(sk), size, sk->sk_sndbuf);

View File

@ -1,348 +0,0 @@
--- /dev/null
+++ b/include/linux/udp_redirect.h
@@ -0,0 +1,57 @@
+#ifndef _UDP_REDIRECT_H
+#define _UDP_REDIRECT_H
+
+/******************************************************************************
+
+ Copyright (c) 2006
+ Infineon Technologies AG
+ Am Campeon 1-12; 81726 Munich, Germany
+
+ THE DELIVERY OF THIS SOFTWARE AS WELL AS THE HEREBY GRANTED NON-EXCLUSIVE,
+ WORLDWIDE LICENSE TO USE, COPY, MODIFY, DISTRIBUTE AND SUBLICENSE THIS
+ SOFTWARE IS FREE OF CHARGE.
+
+ THE LICENSED SOFTWARE IS PROVIDED "AS IS" AND INFINEON EXPRESSLY DISCLAIMS
+ ALL REPRESENTATIONS AND WARRANTIES, WHETHER EXPRESS OR IMPLIED, INCLUDING
+ WITHOUT LIMITATION, WARRANTIES OR REPRESENTATIONS OF WORKMANSHIP,
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, THAT THE
+ OPERATING OF THE LICENSED SOFTWARE WILL BE ERROR FREE OR FREE OF ANY THIRD
+ PARTY CLAIMS, INCLUDING WITHOUT LIMITATION CLAIMS OF THIRD PARTY INTELLECTUAL
+ PROPERTY INFRINGEMENT.
+
+ EXCEPT FOR ANY LIABILITY DUE TO WILFUL ACTS OR GROSS NEGLIGENCE AND EXCEPT
+ FOR ANY PERSONAL INJURY INFINEON SHALL IN NO EVENT BE LIABLE FOR ANY CLAIM
+ OR DAMAGES OF ANY KIND, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+******************************************************************************/
+
+/* ============================= */
+/* Includes */
+/* ============================= */
+#ifndef _LINUX_TYPES_H
+#include <linux/types.h>
+#endif
+
+
+/* ============================= */
+/* Definitions */
+/* ============================= */
+#define UDP_REDIRECT_MAGIC (void*)0x55445052L
+
+
+/* ============================= */
+/* Global variable declaration */
+/* ============================= */
+extern int (*udp_do_redirect_fn)(struct sock *sk, struct sk_buff *skb);
+extern int (*udpredirect_getfrag_fn)(void *p, char * to,
+ int offset, int fraglen, int odd,
+ struct sk_buff *skb);
+/* ============================= */
+/* Global function declaration */
+/* ============================= */
+
+extern int udpredirect_getfrag(void *p, char * to, int offset,
+ int fraglen, int odd, struct sk_buff *skb);
+#endif
--- /dev/null
+++ b/net/ipv4/udp_redirect_symb.c
@@ -0,0 +1,186 @@
+/******************************************************************************
+
+ Copyright (c) 2006
+ Infineon Technologies AG
+ Am Campeon 1-12; 81726 Munich, Germany
+
+ THE DELIVERY OF THIS SOFTWARE AS WELL AS THE HEREBY GRANTED NON-EXCLUSIVE,
+ WORLDWIDE LICENSE TO USE, COPY, MODIFY, DISTRIBUTE AND SUBLICENSE THIS
+ SOFTWARE IS FREE OF CHARGE.
+
+ THE LICENSED SOFTWARE IS PROVIDED "AS IS" AND INFINEON EXPRESSLY DISCLAIMS
+ ALL REPRESENTATIONS AND WARRANTIES, WHETHER EXPRESS OR IMPLIED, INCLUDING
+ WITHOUT LIMITATION, WARRANTIES OR REPRESENTATIONS OF WORKMANSHIP,
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, THAT THE
+ OPERATING OF THE LICENSED SOFTWARE WILL BE ERROR FREE OR FREE OF ANY THIRD
+ PARTY CLAIMS, INCLUDING WITHOUT LIMITATION CLAIMS OF THIRD PARTY INTELLECTUAL
+ PROPERTY INFRINGEMENT.
+
+ EXCEPT FOR ANY LIABILITY DUE TO WILFUL ACTS OR GROSS NEGLIGENCE AND EXCEPT
+ FOR ANY PERSONAL INJURY INFINEON SHALL IN NO EVENT BE LIABLE FOR ANY CLAIM
+ OR DAMAGES OF ANY KIND, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ DEALINGS IN THE SOFTWARE.
+
+******************************************************************************/
+#if defined(CONFIG_IFX_UDP_REDIRECT) || defined(CONFIG_IFX_UDP_REDIRECT_MODULE)
+/* ============================= */
+/* Includes */
+/* ============================= */
+#include <net/checksum.h>
+#include <net/udp.h>
+#include <linux/module.h>
+#include <linux/skbuff.h>
+#include <linux/udp_redirect.h>
+
+/* ============================= */
+/* Global variable definition */
+/* ============================= */
+int (*udpredirect_getfrag_fn) (void *p, char * to, int offset,
+ int fraglen, int odd, struct sk_buff *skb) = NULL;
+int (*udp_do_redirect_fn)(struct sock *sk, struct sk_buff *skb) = NULL;
+
+/* ============================= */
+/* Local type definitions */
+/* ============================= */
+struct udpfakehdr
+{
+ struct udphdr uh;
+ u32 saddr;
+ u32 daddr;
+ struct iovec *iov;
+ u32 wcheck;
+};
+
+/* ============================= */
+/* Local function declaration */
+/* ============================= */
+static int udpredirect_csum_partial_copy_fromiovecend(unsigned char *kdata,
+ struct iovec *iov, int offset, unsigned int len, __wsum *csump);
+
+static int udpredirect_memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, int offset,
+ int len);
+
+/* ============================= */
+/* Global function definition */
+/* ============================= */
+
+/*
+ Copy of udp_getfrag() from udp.c
+ This function exists because no copy_from_user() is needed for udpredirect.
+*/
+
+int
+udpredirect_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb)
+{
+ struct iovec *iov = from;
+
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ if (udpredirect_memcpy_fromiovecend(to, iov, offset, len) < 0)
+ return -EFAULT;
+ } else {
+ __wsum csum = 0;
+ if (udpredirect_csum_partial_copy_fromiovecend(to, iov, offset, len, &csum) < 0)
+ return -EFAULT;
+ skb->csum = csum_block_add(skb->csum, csum, odd);
+ }
+ return 0;
+}
+
+static int udpredirect_memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, int offset,
+ int len)
+{
+ /* Skip over the finished iovecs */
+ while (offset >= iov->iov_len) {
+ offset -= iov->iov_len;
+ iov++;
+ }
+
+ while (len > 0) {
+ u8 __user *base = iov->iov_base + offset;
+ int copy = min_t(unsigned int, len, iov->iov_len - offset);
+
+ offset = 0;
+ memcpy(kdata, base, copy);
+ len -= copy;
+ kdata += copy;
+ iov++;
+ }
+
+ return 0;
+}
+
+/*
+ Copy of csum_partial_copy_fromiovecend() from iovec.c
+ This function exists because no copy_from_user() is needed for udpredirect.
+*/
+
+int udpredirect_csum_partial_copy_fromiovecend(unsigned char *kdata, struct iovec *iov,
+ int offset, unsigned int len, __wsum *csump)
+{
+ __wsum csum = *csump;
+ int partial_cnt = 0, err = 0;
+
+ /* Skip over the finished iovecs */
+ while (offset >= iov->iov_len) {
+ offset -= iov->iov_len;
+ iov++;
+ }
+
+ while (len > 0) {
+ u8 __user *base = iov->iov_base + offset;
+ int copy = min_t(unsigned int, len, iov->iov_len - offset);
+
+ offset = 0;
+
+ /* There is a remnant from previous iov. */
+ if (partial_cnt) {
+ int par_len = 4 - partial_cnt;
+
+ /* iov component is too short ... */
+ if (par_len > copy) {
+ memcpy(kdata, base, copy);
+ kdata += copy;
+ base += copy;
+ partial_cnt += copy;
+ len -= copy;
+ iov++;
+ if (len)
+ continue;
+ *csump = csum_partial(kdata - partial_cnt,
+ partial_cnt, csum);
+ goto out;
+ }
+ memcpy(kdata, base, par_len);
+ csum = csum_partial(kdata - partial_cnt, 4, csum);
+ kdata += par_len;
+ base += par_len;
+ copy -= par_len;
+ len -= par_len;
+ partial_cnt = 0;
+ }
+
+ if (len > copy) {
+ partial_cnt = copy % 4;
+ if (partial_cnt) {
+ copy -= partial_cnt;
+ memcpy(kdata + copy, base + copy, partial_cnt);
+ }
+ }
+
+ if (copy) {
+ csum = csum_partial_copy_nocheck(base, kdata, copy, csum);
+ }
+ len -= copy + partial_cnt;
+ kdata += copy + partial_cnt;
+ iov++;
+ }
+ *csump = csum;
+out:
+ return err;
+}
+
+EXPORT_SYMBOL(udpredirect_getfrag);
+EXPORT_SYMBOL(udp_do_redirect_fn);
+EXPORT_SYMBOL(udpredirect_getfrag_fn);
+#endif /* CONFIG_IFX_UDP_REDIRECT* */
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -14,6 +14,9 @@ obj-y := route.o inetpeer.o protocol
inet_fragment.o
obj-$(CONFIG_SYSCTL) += sysctl_net_ipv4.o
+ifneq ($(CONFIG_IFX_UDP_REDIRECT),)
+obj-$(CONFIG_IFX_UDP_REDIRECT) += udp_redirect_symb.o
+endif
obj-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o
obj-$(CONFIG_IP_MROUTE) += ipmr.o
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -107,6 +107,10 @@
#include <net/xfrm.h>
#include "udp_impl.h"
+#if defined(CONFIG_IFX_UDP_REDIRECT) || defined(CONFIG_IFX_UDP_REDIRECT_MODULE)
+#include <linux/udp_redirect.h>
+#endif
+
struct udp_table udp_table __read_mostly;
EXPORT_SYMBOL(udp_table);
@@ -802,7 +806,7 @@ int udp_sendmsg(struct kiocb *iocb, stru
u8 tos;
int err, is_udplite = IS_UDPLITE(sk);
int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
- int (*getfrag)(void *, char *, int, int, int, struct sk_buff *);
+ int (*getfrag)(void *, char *, int, int, int, struct sk_buff *) = NULL;
struct sk_buff *skb;
if (len > 0xFFFF)
@@ -818,7 +822,13 @@ int udp_sendmsg(struct kiocb *iocb, stru
ipc.opt = NULL;
ipc.tx_flags = 0;
- getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag;
+/* UDPREDIRECT */
+#if defined(CONFIG_IFX_UDP_REDIRECT) || defined(CONFIG_IFX_UDP_REDIRECT_MODULE)
+ if(udpredirect_getfrag_fn && sk->sk_user_data == UDP_REDIRECT_MAGIC)
+ getfrag = udpredirect_getfrag_fn;
+ else
+#endif /* IFX_UDP_REDIRECT */
+ getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag;
if (up->pending) {
/*
@@ -1608,6 +1618,7 @@ int __udp4_lib_rcv(struct sk_buff *skb,
struct rtable *rt = skb_rtable(skb);
__be32 saddr, daddr;
struct net *net = dev_net(skb->dev);
+ int ret = 0;
/*
* Validate the packet.
@@ -1640,7 +1651,16 @@ int __udp4_lib_rcv(struct sk_buff *skb,
sk = __udp4_lib_lookup_skb(skb, uh->source, uh->dest, udptable);
if (sk != NULL) {
- int ret = udp_queue_rcv_skb(sk, skb);
+ /* UDPREDIRECT */
+#if defined(CONFIG_IFX_UDP_REDIRECT) || defined(CONFIG_IFX_UDP_REDIRECT_MODULE)
+ if(udp_do_redirect_fn && sk->sk_user_data == UDP_REDIRECT_MAGIC)
+ {
+ udp_do_redirect_fn(sk,skb);
+ kfree_skb(skb);
+ return(0);
+ }
+#endif
+ ret = udp_queue_rcv_skb(sk, skb);
sock_put(sk);
/* a return value > 0 means to resubmit the input, but
@@ -1937,7 +1957,7 @@ struct proto udp_prot = {
.clear_sk = sk_prot_clear_portaddr_nulls,
};
EXPORT_SYMBOL(udp_prot);
-
+EXPORT_SYMBOL(udp_rcv);
/* ------------------------------------------------------------------------ */
#ifdef CONFIG_PROC_FS
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -72,6 +72,12 @@ config INET
Short answer: say Y.
+config IFX_UDP_REDIRECT
+ bool "IFX Kernel Packet Interface for UDP redirection"
+ help
+ You can say Y here if you want to use hooks from kernel for
+ UDP redirection.
+
if INET
source "net/ipv4/Kconfig"
source "net/ipv6/Kconfig"

View File

@ -1,301 +0,0 @@
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1878,6 +1878,28 @@ config IFX_VPE_EXT
help
IFX included extensions in APRP
+config IFX_VPE_CACHE_SPLIT
+ bool "IFX Cache Split Ways"
+ depends on IFX_VPE_EXT
+ help
+ IFX extension for reserving (splitting) cache ways among VPEs. You must
+ give kernel command line arguments vpe_icache_shared=0 or
+ vpe_dcache_shared=0 to enable splitting of icache or dcache
+ respectively. Then you can specify which cache ways should be
+ assigned to which VPE. There are total 8 cache ways, 4 each
+ for dcache and icache: dcache_way0, dcache_way1,dcache_way2,
+ dcache_way3 and icache_way0,icache_way1, icache_way2,icache_way3.
+
+ For example, if you specify vpe_icache_shared=0 and icache_way2=1,
+ then the 3rd icache way will be assigned to VPE0 and denied in VPE1.
+
+ For icache, software is required to make at least one cache way available
+ for a VPE at all times i.e., one can't assign all the icache ways to one
+ VPE.
+
+ By default, vpe_dcache_shared and vpe_icache_shared are set to 1
+ (i.e., both icache and dcache are shared among VPEs)
+
config PERFCTRS
bool "34K Performance counters"
depends on MIPS_MT && PROC_FS
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -128,6 +128,13 @@ __setup("vpe1_wdog_timeout=", wdog_timeo
EXPORT_SYMBOL(vpe1_wdog_timeout);
#endif
+
+#ifdef CONFIG_IFX_VPE_CACHE_SPLIT /* Code for splitting the cache ways among VPEs. */
+extern int vpe_icache_shared,vpe_dcache_shared;
+extern int icache_way0,icache_way1,icache_way2,icache_way3;
+extern int dcache_way0,dcache_way1,dcache_way2,dcache_way3;
+#endif
+
/* grab the likely amount of memory we will need. */
#ifdef CONFIG_MIPS_VPE_LOADER_TOM
#define P_SIZE (2 * 1024 * 1024)
@@ -866,6 +873,65 @@ static int vpe_run(struct vpe * v)
/* enable this VPE */
write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);
+#ifdef CONFIG_IFX_VPE_CACHE_SPLIT
+ if ( (!vpe_icache_shared) || (!vpe_dcache_shared) ) {
+
+ /* PCP bit must be 1 to split the cache */
+ if(read_c0_mvpconf0() & MVPCONF0_PCP) {
+
+ if ( !vpe_icache_shared ){
+ write_vpe_c0_vpeconf0((read_vpe_c0_vpeconf0()) & ~VPECONF0_ICS);
+
+ /*
+ * If any cache way is 1, then that way is denied
+ * in VPE1. Otherwise assign that way to VPE1.
+ */
+ if (!icache_way0)
+ write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() | VPEOPT_IWX0 );
+ else
+ write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() & ~VPEOPT_IWX0 );
+ if (!icache_way1)
+ write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() | VPEOPT_IWX1 );
+ else
+ write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() & ~VPEOPT_IWX1 );
+ if (!icache_way2)
+ write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() | VPEOPT_IWX2 );
+ else
+ write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() & ~VPEOPT_IWX2 );
+ if (!icache_way3)
+ write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() | VPEOPT_IWX3 );
+ else
+ write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() & ~VPEOPT_IWX3 );
+ }
+
+ if ( !vpe_dcache_shared ) {
+ write_vpe_c0_vpeconf0((read_vpe_c0_vpeconf0()) & ~VPECONF0_DCS);
+
+ /*
+ * If any cache way is 1, then that way is denied
+ * in VPE1. Otherwise assign that way to VPE1.
+ */
+ if (!dcache_way0)
+ write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() | VPEOPT_DWX0 );
+ else
+ write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() & ~VPEOPT_DWX0 );
+ if (!dcache_way1)
+ write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() | VPEOPT_DWX1 );
+ else
+ write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() & ~VPEOPT_DWX1 );
+ if (!dcache_way2)
+ write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() | VPEOPT_DWX2 );
+ else
+ write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() & ~VPEOPT_DWX2 );
+ if (!dcache_way3)
+ write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() | VPEOPT_DWX3 );
+ else
+ write_vpe_c0_vpeopt(read_vpe_c0_vpeopt() & ~VPEOPT_DWX3 );
+ }
+ }
+ }
+#endif /* endif CONFIG_IFX_VPE_CACHE_SPLIT */
+
/* clear out any left overs from a previous program */
write_vpe_c0_status(0);
write_vpe_c0_cause(0);
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -1345,6 +1345,106 @@ static int __init setcoherentio(char *st
__setup("coherentio", setcoherentio);
#endif
+#ifdef CONFIG_IFX_VPE_CACHE_SPLIT /* Code for splitting the cache ways among VPEs. */
+
+#include <asm/mipsmtregs.h>
+
+/*
+ * By default, vpe_icache_shared and vpe_dcache_shared
+ * values are 1 i.e., both icache and dcache are shared
+ * among the VPEs.
+ */
+
+int vpe_icache_shared = 1;
+static int __init vpe_icache_shared_val(char *str)
+{
+ get_option(&str, &vpe_icache_shared);
+ return 1;
+}
+__setup("vpe_icache_shared=", vpe_icache_shared_val);
+EXPORT_SYMBOL(vpe_icache_shared);
+
+int vpe_dcache_shared = 1;
+static int __init vpe_dcache_shared_val(char *str)
+{
+ get_option(&str, &vpe_dcache_shared);
+ return 1;
+}
+__setup("vpe_dcache_shared=", vpe_dcache_shared_val);
+EXPORT_SYMBOL(vpe_dcache_shared);
+
+/*
+ * Software is required to make atleast one icache
+ * way available for a VPE at all times i.e., one
+ * can't assign all the icache ways to one VPE.
+ */
+
+int icache_way0 = 0;
+static int __init icache_way0_val(char *str)
+{
+ get_option(&str, &icache_way0);
+ return 1;
+}
+__setup("icache_way0=", icache_way0_val);
+
+int icache_way1 = 0;
+static int __init icache_way1_val(char *str)
+{
+ get_option(&str, &icache_way1);
+ return 1;
+}
+__setup("icache_way1=", icache_way1_val);
+
+int icache_way2 = 0;
+static int __init icache_way2_val(char *str)
+{
+ get_option(&str, &icache_way2);
+ return 1;
+}
+__setup("icache_way2=", icache_way2_val);
+
+int icache_way3 = 0;
+static int __init icache_way3_val(char *str)
+{
+ get_option(&str, &icache_way3);
+ return 1;
+}
+__setup("icache_way3=", icache_way3_val);
+
+int dcache_way0 = 0;
+static int __init dcache_way0_val(char *str)
+{
+ get_option(&str, &dcache_way0);
+ return 1;
+}
+__setup("dcache_way0=", dcache_way0_val);
+
+int dcache_way1 = 0;
+static int __init dcache_way1_val(char *str)
+{
+ get_option(&str, &dcache_way1);
+ return 1;
+}
+__setup("dcache_way1=", dcache_way1_val);
+
+int dcache_way2 = 0;
+static int __init dcache_way2_val(char *str)
+{
+ get_option(&str, &dcache_way2);
+ return 1;
+}
+__setup("dcache_way2=", dcache_way2_val);
+
+int dcache_way3 = 0;
+static int __init dcache_way3_val(char *str)
+{
+ get_option(&str, &dcache_way3);
+ return 1;
+}
+__setup("dcache_way3=", dcache_way3_val);
+
+#endif /* endif CONFIG_IFX_VPE_CACHE_SPLIT */
+
void __cpuinit r4k_cache_init(void)
{
extern void build_clear_page(void);
@@ -1364,6 +1464,78 @@ void __cpuinit r4k_cache_init(void)
break;
}
+#ifdef CONFIG_IFX_VPE_CACHE_SPLIT
+ /*
+ * We split the cache ways appropriately among the VPEs
+ * based on cache ways values we received as command line
+ * arguments
+ */
+ if ( (!vpe_icache_shared) || (!vpe_dcache_shared) ){
+
+ /* PCP bit must be 1 to split the cache */
+ if(read_c0_mvpconf0() & MVPCONF0_PCP) {
+
+ /* Set CPA bit which enables us to modify VPEOpt register */
+ write_c0_mvpcontrol((read_c0_mvpcontrol()) | MVPCONTROL_CPA);
+
+ if ( !vpe_icache_shared ){
+ write_c0_vpeconf0((read_c0_vpeconf0()) & ~VPECONF0_ICS);
+ /*
+ * If any cache way is 1, then that way is denied
+ * in VPE0. Otherwise assign that way to VPE0.
+ */
+ printk(KERN_DEBUG "icache is split\n");
+ printk(KERN_DEBUG "icache_way0=%d icache_way1=%d icache_way2=%d icache_way3=%d\n",
+ icache_way0, icache_way1,icache_way2, icache_way3);
+ if (icache_way0)
+ write_c0_vpeopt(read_c0_vpeopt() | VPEOPT_IWX0 );
+ else
+ write_c0_vpeopt(read_c0_vpeopt() & ~VPEOPT_IWX0 );
+ if (icache_way1)
+ write_c0_vpeopt(read_c0_vpeopt() | VPEOPT_IWX1 );
+ else
+ write_c0_vpeopt(read_c0_vpeopt() & ~VPEOPT_IWX1 );
+ if (icache_way2)
+ write_c0_vpeopt(read_c0_vpeopt() | VPEOPT_IWX2 );
+ else
+ write_c0_vpeopt(read_c0_vpeopt() & ~VPEOPT_IWX2 );
+ if (icache_way3)
+ write_c0_vpeopt(read_c0_vpeopt() | VPEOPT_IWX3 );
+ else
+ write_c0_vpeopt(read_c0_vpeopt() & ~VPEOPT_IWX3 );
+ }
+
+ if ( !vpe_dcache_shared ) {
+ /*
+ * If any cache way is 1, then that way is denied
+ * in VPE0. Otherwise assign that way to VPE0.
+ */
+ printk(KERN_DEBUG "dcache is split\n");
+ printk(KERN_DEBUG "dcache_way0=%d dcache_way1=%d dcache_way2=%d dcache_way3=%d\n",
+ dcache_way0, dcache_way1, dcache_way2, dcache_way3);
+ write_c0_vpeconf0((read_c0_vpeconf0()) & ~VPECONF0_DCS);
+ if (dcache_way0)
+ write_c0_vpeopt(read_c0_vpeopt() | VPEOPT_DWX0 );
+ else
+ write_c0_vpeopt(read_c0_vpeopt() & ~VPEOPT_DWX0 );
+ if (dcache_way1)
+ write_c0_vpeopt(read_c0_vpeopt() | VPEOPT_DWX1 );
+ else
+ write_c0_vpeopt(read_c0_vpeopt() & ~VPEOPT_DWX1 );
+ if (dcache_way2)
+ write_c0_vpeopt(read_c0_vpeopt() | VPEOPT_DWX2 );
+ else
+ write_c0_vpeopt(read_c0_vpeopt() & ~VPEOPT_DWX2 );
+ if (dcache_way3)
+ write_c0_vpeopt(read_c0_vpeopt() | VPEOPT_DWX3 );
+ else
+ write_c0_vpeopt(read_c0_vpeopt() & ~VPEOPT_DWX3 );
+ }
+ }
+ }
+
+#endif /* endif CONFIG_IFX_VPE_CACHE_SPLIT */
+
probe_pcache();
setup_scache();

View File

@ -1,8 +0,0 @@
--- a/drivers/mtd/devices/m25p80.c
+++ b/drivers/mtd/devices/m25p80.c
@@ -1,3 +1,5 @@
+
+
/*
* MTD SPI driver for ST M25Pxx (and similar) serial flash chips
*

View File

@ -1,17 +0,0 @@
--- a/drivers/net/lantiq_etop.c
+++ b/drivers/net/lantiq_etop.c
@@ -155,8 +155,12 @@ ltq_etop_hw_receive(struct ltq_etop_chan
skb_put(skb, len);
skb->dev = ch->netdev;
- skb->protocol = eth_type_trans(skb, ch->netdev);
- netif_receive_skb(skb);
+ if (priv->phydev && priv->phydev->netif_receive_skb) {
+ priv->phydev->netif_receive_skb(skb);
+ } else {
+ skb->protocol = eth_type_trans(skb, ch->netdev);
+ netif_receive_skb(skb);
+ }
}
static int

View File

@ -1,116 +0,0 @@
--- a/drivers/net/dm9000.c
+++ b/drivers/net/dm9000.c
@@ -19,6 +19,7 @@
* Sascha Hauer <s.hauer@pengutronix.de>
*/
+#define DEBUG
#include <linux/module.h>
#include <linux/ioport.h>
#include <linux/netdevice.h>
@@ -125,6 +126,8 @@ typedef struct board_info {
struct delayed_work phy_poll;
struct net_device *ndev;
+ struct delayed_work irq_poll; /* for use in irq polling mode */
+
spinlock_t lock;
struct mii_if_info mii;
@@ -855,6 +858,8 @@ static void dm9000_timeout(struct net_de
netif_stop_queue(dev);
dm9000_reset(db);
dm9000_init_dm9000(dev);
+ dm9000_reset(db);
+ dm9000_init_dm9000(dev);
/* We can accept TX packets again */
dev->trans_start = jiffies; /* prevent tx timeout */
netif_wake_queue(dev);
@@ -926,6 +931,12 @@ dm9000_start_xmit(struct sk_buff *skb, s
/* free this SKB */
dev_kfree_skb(skb);
+ /* directly poll afterwards */
+ if (dev->irq == -1) {
+ cancel_delayed_work(&db->irq_poll);
+ schedule_delayed_work(&db->irq_poll, 1);
+ }
+
return NETDEV_TX_OK;
}
@@ -1167,6 +1178,18 @@ static void dm9000_poll_controller(struc
}
#endif
+static void dm9000_poll_irq(struct work_struct *w)
+{
+ struct delayed_work *dw = to_delayed_work(w);
+ board_info_t *db = container_of(dw, board_info_t, irq_poll);
+ struct net_device *ndev = db->ndev;
+
+ dm9000_interrupt(0, ndev);
+
+ if (netif_running(ndev))
+ schedule_delayed_work(&db->irq_poll, HZ /100);
+}
+
/*
* Open the interface.
* The interface is opened whenever "ifconfig" actives it.
@@ -1180,17 +1203,18 @@ dm9000_open(struct net_device *dev)
if (netif_msg_ifup(db))
dev_dbg(db->dev, "enabling %s\n", dev->name);
- /* If there is no IRQ type specified, default to something that
- * may work, and tell the user that this is a problem */
+ if (dev->irq != -1) {
+ /* If there is no IRQ type specified, default to something that
+ * may work, and tell the user that this is a problem */
- if (irqflags == IRQF_TRIGGER_NONE)
- dev_warn(db->dev, "WARNING: no IRQ resource flags set.\n");
+ if (irqflags == IRQF_TRIGGER_NONE)
+ dev_warn(db->dev, "WARNING: no IRQ resource flags set.\n");
- irqflags |= IRQF_SHARED;
-
- if (request_irq(dev->irq, dm9000_interrupt, irqflags, dev->name, dev))
- return -EAGAIN;
+ irqflags |= IRQF_SHARED;
+ if (request_irq(dev->irq, dm9000_interrupt, irqflags, dev->name, dev))
+ return -EAGAIN;
+ }
/* GPIO0 on pre-activate PHY, Reg 1F is not set by reset */
iow(db, DM9000_GPR, 0); /* REG_1F bit0 activate phyxcer */
mdelay(1); /* delay needs by DM9000B */
@@ -1198,13 +1222,19 @@ dm9000_open(struct net_device *dev)
/* Initialize DM9000 board */
dm9000_reset(db);
dm9000_init_dm9000(dev);
+ /* testing: init a second time */
+ dm9000_reset(db);
+ dm9000_init_dm9000(dev);
/* Init driver variable */
db->dbug_cnt = 0;
mii_check_media(&db->mii, netif_msg_link(db), 1);
netif_start_queue(dev);
-
+
+ if (dev->irq == -1)
+ schedule_delayed_work(&db->irq_poll, HZ / 100);
+
dm9000_schedule_poll(db);
return 0;
@@ -1401,6 +1431,7 @@ dm9000_probe(struct platform_device *pde
mutex_init(&db->addr_lock);
INIT_DELAYED_WORK(&db->phy_poll, dm9000_poll_work);
+ INIT_DELAYED_WORK(&db->irq_poll, dm9000_poll_irq);
db->addr_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
db->data_res = platform_get_resource(pdev, IORESOURCE_MEM, 1);

View File

@ -1,36 +0,0 @@
From: Daniel Schwierzeck <daniel.schwierzeck@googlemail.com>
Date: Thu, 3 Mar 2011 17:15:58 +0000 (+0100)
Subject: MIPS: lantiq: Add platform data for Lantiq SoC SPI controller driver
X-Git-Url: http://nbd.name/gitweb.cgi?p=lantiq.git;a=commitdiff_plain;h=3d21b04682ae8eb1c1965aba39d1796e8c5ad84b;hp=06b420500fe98e37662837e78d8e51aead8aea81
MIPS: lantiq: Add platform data for Lantiq SoC SPI controller driver
Signed-off-by: Daniel Schwierzeck <daniel.schwierzeck@googlemail.com>
---
--- a/arch/mips/include/asm/mach-lantiq/lantiq_platform.h
+++ b/arch/mips/include/asm/mach-lantiq/lantiq_platform.h
@@ -50,4 +50,13 @@ struct ltq_eth_data {
int mii_mode;
};
+
+struct ltq_spi_platform_data {
+ u16 num_chipselect;
+};
+
+struct ltq_spi_controller_data {
+ unsigned gpio;
+};
+
#endif
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
@@ -75,6 +75,7 @@
#define PMU_DMA 0x0020
#define PMU_USB 0x8041
+#define PMU_SPI 0x0100
#define PMU_LED 0x0800
#define PMU_GPT 0x1000
#define PMU_PPE 0x2000

File diff suppressed because it is too large Load Diff

View File

@ -1,73 +0,0 @@
From: Daniel Schwierzeck <daniel.schwierzeck@googlemail.com>
Date: Thu, 3 Mar 2011 20:42:26 +0000 (+0100)
Subject: MIPS: lantiq: Add device register helper for SPI controller and devices
X-Git-Url: http://nbd.name/gitweb.cgi?p=lantiq.git;a=commitdiff_plain;h=b35b07062b718ece9b9cb7b23b12d83a087eafb0;hp=653c95b8b9066c9c6ac08bd64d0ceee439e9fd90
MIPS: lantiq: Add device register helper for SPI controller and devices
Signed-off-by: Daniel Schwierzeck <daniel.schwierzeck@googlemail.com>
---
--- a/arch/mips/lantiq/xway/devices.c
+++ b/arch/mips/lantiq/xway/devices.c
@@ -21,6 +21,7 @@
#include <linux/io.h>
#include <linux/gpio.h>
#include <linux/leds.h>
+#include <linux/spi/spi.h>
#include <asm/bootinfo.h>
#include <asm/irq.h>
@@ -119,3 +120,41 @@ ltq_register_etop(struct ltq_eth_data *e
platform_device_register(&ltq_etop);
}
}
+
+static struct resource ltq_spi_resources[] = {
+ {
+ .start = LTQ_SSC_BASE_ADDR,
+ .end = LTQ_SSC_BASE_ADDR + LTQ_SSC_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ IRQ_RES(spi_tx, LTQ_SSC_TIR),
+ IRQ_RES(spi_rx, LTQ_SSC_RIR),
+ IRQ_RES(spi_err, LTQ_SSC_EIR),
+};
+
+static struct resource ltq_spi_resources_ar9[] = {
+ {
+ .start = LTQ_SSC_BASE_ADDR,
+ .end = LTQ_SSC_BASE_ADDR + LTQ_SSC_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+ },
+ IRQ_RES(spi_tx, LTQ_SSC_TIR_AR9),
+ IRQ_RES(spi_rx, LTQ_SSC_RIR_AR9),
+ IRQ_RES(spi_err, LTQ_SSC_EIR),
+};
+
+static struct platform_device ltq_spi = {
+ .name = "ltq-spi",
+ .resource = ltq_spi_resources,
+ .num_resources = ARRAY_SIZE(ltq_spi_resources),
+};
+
+void __init ltq_register_spi(struct ltq_spi_platform_data *pdata,
+ struct spi_board_info const *info, unsigned n)
+{
+ if(ltq_is_ar9())
+ ltq_spi.resource = ltq_spi_resources_ar9;
+ spi_register_board_info(info, n);
+ ltq_spi.dev.platform_data = pdata;
+ platform_device_register(&ltq_spi);
+}
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
@@ -27,6 +27,8 @@
#define LTQ_SSC_TIR (INT_NUM_IM0_IRL0 + 15)
#define LTQ_SSC_RIR (INT_NUM_IM0_IRL0 + 14)
+#define LTQ_SSC_TIR_AR9 (INT_NUM_IM0_IRL0 + 14)
+#define LTQ_SSC_RIR_AR9 (INT_NUM_IM0_IRL0 + 15)
#define LTQ_SSC_EIR (INT_NUM_IM0_IRL0 + 16)
#define LTQ_MEI_DYING_GASP_INT (INT_NUM_IM1_IRL0 + 21)

View File

@ -1,41 +0,0 @@
--- a/arch/mips/lantiq/xway/devices.c
+++ b/arch/mips/lantiq/xway/devices.c
@@ -121,6 +121,29 @@ ltq_register_etop(struct ltq_eth_data *e
}
}
+/* ebu */
+static struct resource ltq_ebu_resource =
+{
+ .name = "gpio_ebu",
+ .start = LTQ_EBU_GPIO_START,
+ .end = LTQ_EBU_GPIO_START + LTQ_EBU_GPIO_SIZE - 1,
+ .flags = IORESOURCE_MEM,
+};
+
+static struct platform_device ltq_ebu =
+{
+ .name = "ltq_ebu",
+ .resource = &ltq_ebu_resource,
+ .num_resources = 1,
+};
+
+void __init
+ltq_register_gpio_ebu(unsigned int value)
+{
+ ltq_ebu.dev.platform_data = (void*) value;
+ platform_device_register(&ltq_ebu);
+}
+
static struct resource ltq_spi_resources[] = {
{
.start = LTQ_SSC_BASE_ADDR,
--- a/arch/mips/lantiq/xway/devices.h
+++ b/arch/mips/lantiq/xway/devices.h
@@ -16,5 +16,6 @@ extern void ltq_register_gpio(void);
extern void ltq_register_gpio_stp(void);
extern void ltq_register_ase_asc(void);
extern void ltq_register_etop(struct ltq_eth_data *eth);
+extern void ltq_register_gpio_ebu(unsigned int value);
#endif

View File

@ -1,31 +0,0 @@
--- a/arch/mips/lantiq/xway/devices.c
+++ b/arch/mips/lantiq/xway/devices.c
@@ -144,6 +144,19 @@ ltq_register_gpio_ebu(unsigned int value
platform_device_register(&ltq_ebu);
}
+/* madwifi */
+int lantiq_emulate_madwifi_eep = 0;
+unsigned long long lantiq_madwifi_eep_addr = 0;
+EXPORT_SYMBOL(lantiq_emulate_madwifi_eep);
+EXPORT_SYMBOL(lantiq_madwifi_eep_addr);
+
+void __init
+ltq_register_madwifi_eep(unsigned long long addr)
+{
+ lantiq_emulate_madwifi_eep = 1;
+ lantiq_madwifi_eep_addr = addr;
+}
+
static struct resource ltq_spi_resources[] = {
{
.start = LTQ_SSC_BASE_ADDR,
--- a/arch/mips/lantiq/xway/devices.h
+++ b/arch/mips/lantiq/xway/devices.h
@@ -17,5 +17,6 @@ extern void ltq_register_gpio_stp(void);
extern void ltq_register_ase_asc(void);
extern void ltq_register_etop(struct ltq_eth_data *eth);
extern void ltq_register_gpio_ebu(unsigned int value);
+extern void ltq_register_madwifi_eep(unsigned long long addr);
#endif

View File

@ -1,101 +0,0 @@
--- a/arch/mips/lantiq/Makefile
+++ b/arch/mips/lantiq/Makefile
@@ -4,7 +4,7 @@
# under the terms of the GNU General Public License version 2 as published
# by the Free Software Foundation.
-obj-y := irq.o setup.o clk.o prom.o devices.o
+obj-y := irq.o setup.o clk.o prom.o devices.o dev-gpio-buttons.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
--- /dev/null
+++ b/arch/mips/lantiq/dev-gpio-buttons.c
@@ -0,0 +1,58 @@
+/*
+ * Lantiq GPIO button support
+ *
+ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * 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.
+ */
+
+#include "linux/init.h"
+#include "linux/slab.h"
+#include <linux/platform_device.h>
+
+#include "dev-gpio-buttons.h"
+
+void __init ltq_register_gpio_keys_polled(int id,
+ unsigned poll_interval,
+ unsigned nbuttons,
+ struct gpio_keys_button *buttons)
+{
+ struct platform_device *pdev;
+ struct gpio_keys_platform_data pdata;
+ struct gpio_keys_button *p;
+ int err;
+
+ p = kmalloc(nbuttons * sizeof(*p), GFP_KERNEL);
+ if (!p)
+ return;
+
+ memcpy(p, buttons, nbuttons * sizeof(*p));
+
+ pdev = platform_device_alloc("gpio-keys-polled", id);
+ if (!pdev)
+ goto err_free_buttons;
+
+ memset(&pdata, 0, sizeof(pdata));
+ pdata.poll_interval = poll_interval;
+ pdata.nbuttons = nbuttons;
+ pdata.buttons = p;
+
+ err = platform_device_add_data(pdev, &pdata, sizeof(pdata));
+ if (err)
+ goto err_put_pdev;
+
+ err = platform_device_add(pdev);
+ if (err)
+ goto err_put_pdev;
+
+ return;
+
+err_put_pdev:
+ platform_device_put(pdev);
+
+err_free_buttons:
+ kfree(p);
+}
--- /dev/null
+++ b/arch/mips/lantiq/dev-gpio-buttons.h
@@ -0,0 +1,26 @@
+/*
+ * Lantiq GPIO button support
+ *
+ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * 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.
+ */
+
+#ifndef _LANTIQ_DEV_GPIO_BUTTONS_H
+#define _LANTIQ_DEV_GPIO_BUTTONS_H
+
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+
+#define LTQ_KEYS_POLL_INTERVAL 20 /* msecs */
+#define LTQ_KEYS_DEBOUNCE_INTERVAL (3 * LTQ_KEYS_POLL_INTERVAL)
+
+void ltq_register_gpio_keys_polled(int id,
+ unsigned poll_interval,
+ unsigned nbuttons,
+ struct gpio_keys_button *buttons);
+
+#endif /* _LANTIQ_DEV_GPIO_BUTTONS_H */

View File

@ -1,42 +0,0 @@
--- a/arch/mips/lantiq/devices.c
+++ b/arch/mips/lantiq/devices.c
@@ -120,3 +120,20 @@ void __init ltq_register_pci(struct ltq_
pr_err("kernel is compiled without PCI support\n");
}
#endif
+
+static unsigned int *cp1_base = 0;
+unsigned int*
+ltq_get_cp1_base(void)
+{
+ return cp1_base;
+}
+EXPORT_SYMBOL(ltq_get_cp1_base);
+
+void __init
+ltq_register_tapi(void)
+{
+#define CP1_SIZE (1 << 20)
+ dma_addr_t dma;
+ cp1_base =
+ (void*)CPHYSADDR(dma_alloc_coherent(NULL, CP1_SIZE, &dma, GFP_ATOMIC));
+}
--- a/arch/mips/lantiq/devices.h
+++ b/arch/mips/lantiq/devices.h
@@ -19,5 +19,6 @@ extern void ltq_register_nor(struct phys
extern void ltq_register_wdt(void);
extern void ltq_register_asc(int port);
extern void ltq_register_pci(struct ltq_pci_data *data);
+extern void ltq_register_tapi(void);
#endif
--- a/arch/mips/lantiq/xway/mach-easy50712.c
+++ b/arch/mips/lantiq/xway/mach-easy50712.c
@@ -61,6 +61,7 @@ static void __init easy50712_init(void)
ltq_register_nor(&easy50712_flash_data);
ltq_register_pci(&ltq_pci_data);
ltq_register_etop(&ltq_eth_data);
+ ltq_register_tapi();
}
MIPS_MACHINE(LTQ_MACH_EASY50712,

View File

@ -1,999 +0,0 @@
--- /dev/null
+++ b/arch/mips/lantiq/xway/timer.c
@@ -0,0 +1,830 @@
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/init.h>
+#include <linux/uaccess.h>
+#include <linux/unistd.h>
+#include <linux/errno.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+
+#include <asm/irq.h>
+#include <asm/div64.h>
+
+#include <lantiq_soc.h>
+#include <lantiq_irq.h>
+#include <lantiq_timer.h>
+
+#define MAX_NUM_OF_32BIT_TIMER_BLOCKS 6
+
+#ifdef TIMER1A
+#define FIRST_TIMER TIMER1A
+#else
+#define FIRST_TIMER 2
+#endif
+
+/*
+ * GPTC divider is set or not.
+ */
+#define GPTU_CLC_RMC_IS_SET 0
+
+/*
+ * Timer Interrupt (IRQ)
+ */
+/* Must be adjusted when ICU driver is available */
+#define TIMER_INTERRUPT (INT_NUM_IM3_IRL0 + 22)
+
+/*
+ * Bits Operation
+ */
+#define GET_BITS(x, msb, lsb) \
+ (((x) & ((1 << ((msb) + 1)) - 1)) >> (lsb))
+#define SET_BITS(x, msb, lsb, value) \
+ (((x) & ~(((1 << ((msb) + 1)) - 1) ^ ((1 << (lsb)) - 1))) | \
+ (((value) & ((1 << (1 + (msb) - (lsb))) - 1)) << (lsb)))
+
+/*
+ * GPTU Register Mapping
+ */
+#define LQ_GPTU (KSEG1 + 0x1E100A00)
+#define LQ_GPTU_CLC ((volatile u32 *)(LQ_GPTU + 0x0000))
+#define LQ_GPTU_ID ((volatile u32 *)(LQ_GPTU + 0x0008))
+#define LQ_GPTU_CON(n, X) ((volatile u32 *)(LQ_GPTU + 0x0010 + ((X) * 4) + ((n) - 1) * 0x0020)) /* X must be either A or B */
+#define LQ_GPTU_RUN(n, X) ((volatile u32 *)(LQ_GPTU + 0x0018 + ((X) * 4) + ((n) - 1) * 0x0020)) /* X must be either A or B */
+#define LQ_GPTU_RELOAD(n, X) ((volatile u32 *)(LQ_GPTU + 0x0020 + ((X) * 4) + ((n) - 1) * 0x0020)) /* X must be either A or B */
+#define LQ_GPTU_COUNT(n, X) ((volatile u32 *)(LQ_GPTU + 0x0028 + ((X) * 4) + ((n) - 1) * 0x0020)) /* X must be either A or B */
+#define LQ_GPTU_IRNEN ((volatile u32 *)(LQ_GPTU + 0x00F4))
+#define LQ_GPTU_IRNICR ((volatile u32 *)(LQ_GPTU + 0x00F8))
+#define LQ_GPTU_IRNCR ((volatile u32 *)(LQ_GPTU + 0x00FC))
+
+/*
+ * Clock Control Register
+ */
+#define GPTU_CLC_SMC GET_BITS(*LQ_GPTU_CLC, 23, 16)
+#define GPTU_CLC_RMC GET_BITS(*LQ_GPTU_CLC, 15, 8)
+#define GPTU_CLC_FSOE (*LQ_GPTU_CLC & (1 << 5))
+#define GPTU_CLC_EDIS (*LQ_GPTU_CLC & (1 << 3))
+#define GPTU_CLC_SPEN (*LQ_GPTU_CLC & (1 << 2))
+#define GPTU_CLC_DISS (*LQ_GPTU_CLC & (1 << 1))
+#define GPTU_CLC_DISR (*LQ_GPTU_CLC & (1 << 0))
+
+#define GPTU_CLC_SMC_SET(value) SET_BITS(0, 23, 16, (value))
+#define GPTU_CLC_RMC_SET(value) SET_BITS(0, 15, 8, (value))
+#define GPTU_CLC_FSOE_SET(value) ((value) ? (1 << 5) : 0)
+#define GPTU_CLC_SBWE_SET(value) ((value) ? (1 << 4) : 0)
+#define GPTU_CLC_EDIS_SET(value) ((value) ? (1 << 3) : 0)
+#define GPTU_CLC_SPEN_SET(value) ((value) ? (1 << 2) : 0)
+#define GPTU_CLC_DISR_SET(value) ((value) ? (1 << 0) : 0)
+
+/*
+ * ID Register
+ */
+#define GPTU_ID_ID GET_BITS(*LQ_GPTU_ID, 15, 8)
+#define GPTU_ID_CFG GET_BITS(*LQ_GPTU_ID, 7, 5)
+#define GPTU_ID_REV GET_BITS(*LQ_GPTU_ID, 4, 0)
+
+/*
+ * Control Register of Timer/Counter nX
+ * n is the index of block (1 based index)
+ * X is either A or B
+ */
+#define GPTU_CON_SRC_EG(n, X) (*LQ_GPTU_CON(n, X) & (1 << 10))
+#define GPTU_CON_SRC_EXT(n, X) (*LQ_GPTU_CON(n, X) & (1 << 9))
+#define GPTU_CON_SYNC(n, X) (*LQ_GPTU_CON(n, X) & (1 << 8))
+#define GPTU_CON_EDGE(n, X) GET_BITS(*LQ_GPTU_CON(n, X), 7, 6)
+#define GPTU_CON_INV(n, X) (*LQ_GPTU_CON(n, X) & (1 << 5))
+#define GPTU_CON_EXT(n, X) (*LQ_GPTU_CON(n, A) & (1 << 4)) /* Timer/Counter B does not have this bit */
+#define GPTU_CON_STP(n, X) (*LQ_GPTU_CON(n, X) & (1 << 3))
+#define GPTU_CON_CNT(n, X) (*LQ_GPTU_CON(n, X) & (1 << 2))
+#define GPTU_CON_DIR(n, X) (*LQ_GPTU_CON(n, X) & (1 << 1))
+#define GPTU_CON_EN(n, X) (*LQ_GPTU_CON(n, X) & (1 << 0))
+
+#define GPTU_CON_SRC_EG_SET(value) ((value) ? 0 : (1 << 10))
+#define GPTU_CON_SRC_EXT_SET(value) ((value) ? (1 << 9) : 0)
+#define GPTU_CON_SYNC_SET(value) ((value) ? (1 << 8) : 0)
+#define GPTU_CON_EDGE_SET(value) SET_BITS(0, 7, 6, (value))
+#define GPTU_CON_INV_SET(value) ((value) ? (1 << 5) : 0)
+#define GPTU_CON_EXT_SET(value) ((value) ? (1 << 4) : 0)
+#define GPTU_CON_STP_SET(value) ((value) ? (1 << 3) : 0)
+#define GPTU_CON_CNT_SET(value) ((value) ? (1 << 2) : 0)
+#define GPTU_CON_DIR_SET(value) ((value) ? (1 << 1) : 0)
+
+#define GPTU_RUN_RL_SET(value) ((value) ? (1 << 2) : 0)
+#define GPTU_RUN_CEN_SET(value) ((value) ? (1 << 1) : 0)
+#define GPTU_RUN_SEN_SET(value) ((value) ? (1 << 0) : 0)
+
+#define GPTU_IRNEN_TC_SET(n, X, value) ((value) ? (1 << (((n) - 1) * 2 + (X))) : 0)
+#define GPTU_IRNCR_TC_SET(n, X, value) ((value) ? (1 << (((n) - 1) * 2 + (X))) : 0)
+
+#define TIMER_FLAG_MASK_SIZE(x) (x & 0x0001)
+#define TIMER_FLAG_MASK_TYPE(x) (x & 0x0002)
+#define TIMER_FLAG_MASK_STOP(x) (x & 0x0004)
+#define TIMER_FLAG_MASK_DIR(x) (x & 0x0008)
+#define TIMER_FLAG_NONE_EDGE 0x0000
+#define TIMER_FLAG_MASK_EDGE(x) (x & 0x0030)
+#define TIMER_FLAG_REAL 0x0000
+#define TIMER_FLAG_INVERT 0x0040
+#define TIMER_FLAG_MASK_INVERT(x) (x & 0x0040)
+#define TIMER_FLAG_MASK_TRIGGER(x) (x & 0x0070)
+#define TIMER_FLAG_MASK_SYNC(x) (x & 0x0080)
+#define TIMER_FLAG_CALLBACK_IN_HB 0x0200
+#define TIMER_FLAG_MASK_HANDLE(x) (x & 0x0300)
+#define TIMER_FLAG_MASK_SRC(x) (x & 0x1000)
+
+struct timer_dev_timer {
+ unsigned int f_irq_on;
+ unsigned int irq;
+ unsigned int flag;
+ unsigned long arg1;
+ unsigned long arg2;
+};
+
+struct timer_dev {
+ struct mutex gptu_mutex;
+ unsigned int number_of_timers;
+ unsigned int occupation;
+ unsigned int f_gptu_on;
+ struct timer_dev_timer timer[MAX_NUM_OF_32BIT_TIMER_BLOCKS * 2];
+};
+
+unsigned int ltq_get_fpi_bus_clock(int fpi);
+
+static long gptu_ioctl(struct file *, unsigned int, unsigned long);
+static int gptu_open(struct inode *, struct file *);
+static int gptu_release(struct inode *, struct file *);
+
+static struct file_operations gptu_fops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = gptu_ioctl,
+ .open = gptu_open,
+ .release = gptu_release
+};
+
+static struct miscdevice gptu_miscdev = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "gptu",
+ .fops = &gptu_fops,
+};
+
+static struct timer_dev timer_dev;
+
+static irqreturn_t timer_irq_handler(int irq, void *p)
+{
+ unsigned int timer;
+ unsigned int flag;
+ struct timer_dev_timer *dev_timer = (struct timer_dev_timer *)p;
+
+ timer = irq - TIMER_INTERRUPT;
+ if (timer < timer_dev.number_of_timers
+ && dev_timer == &timer_dev.timer[timer]) {
+ /* Clear interrupt. */
+ ltq_w32(1 << timer, LQ_GPTU_IRNCR);
+
+ /* Call user hanler or signal. */
+ flag = dev_timer->flag;
+ if (!(timer & 0x01)
+ || TIMER_FLAG_MASK_SIZE(flag) == TIMER_FLAG_16BIT) {
+ /* 16-bit timer or timer A of 32-bit timer */
+ switch (TIMER_FLAG_MASK_HANDLE(flag)) {
+ case TIMER_FLAG_CALLBACK_IN_IRQ:
+ case TIMER_FLAG_CALLBACK_IN_HB:
+ if (dev_timer->arg1)
+ (*(timer_callback)dev_timer->arg1)(dev_timer->arg2);
+ break;
+ case TIMER_FLAG_SIGNAL:
+ send_sig((int)dev_timer->arg2, (struct task_struct *)dev_timer->arg1, 0);
+ break;
+ }
+ }
+ }
+ return IRQ_HANDLED;
+}
+
+static inline void lq_enable_gptu(void)
+{
+ ltq_pmu_enable(PMU_GPT);
+
+ /* Set divider as 1, disable write protection for SPEN, enable module. */
+ *LQ_GPTU_CLC =
+ GPTU_CLC_SMC_SET(0x00) |
+ GPTU_CLC_RMC_SET(0x01) |
+ GPTU_CLC_FSOE_SET(0) |
+ GPTU_CLC_SBWE_SET(1) |
+ GPTU_CLC_EDIS_SET(0) |
+ GPTU_CLC_SPEN_SET(0) |
+ GPTU_CLC_DISR_SET(0);
+}
+
+static inline void lq_disable_gptu(void)
+{
+ ltq_w32(0x00, LQ_GPTU_IRNEN);
+ ltq_w32(0xfff, LQ_GPTU_IRNCR);
+
+ /* Set divider as 0, enable write protection for SPEN, disable module. */
+ *LQ_GPTU_CLC =
+ GPTU_CLC_SMC_SET(0x00) |
+ GPTU_CLC_RMC_SET(0x00) |
+ GPTU_CLC_FSOE_SET(0) |
+ GPTU_CLC_SBWE_SET(0) |
+ GPTU_CLC_EDIS_SET(0) |
+ GPTU_CLC_SPEN_SET(0) |
+ GPTU_CLC_DISR_SET(1);
+
+ ltq_pmu_disable(PMU_GPT);
+}
+
+int lq_request_timer(unsigned int timer, unsigned int flag,
+ unsigned long value, unsigned long arg1, unsigned long arg2)
+{
+ int ret = 0;
+ unsigned int con_reg, irnen_reg;
+ int n, X;
+
+ if (timer >= FIRST_TIMER + timer_dev.number_of_timers)
+ return -EINVAL;
+
+ printk(KERN_INFO "request_timer(%d, 0x%08X, %lu)...",
+ timer, flag, value);
+
+ if (TIMER_FLAG_MASK_SIZE(flag) == TIMER_FLAG_16BIT)
+ value &= 0xFFFF;
+ else
+ timer &= ~0x01;
+
+ mutex_lock(&timer_dev.gptu_mutex);
+
+ /*
+ * Allocate timer.
+ */
+ if (timer < FIRST_TIMER) {
+ unsigned int mask;
+ unsigned int shift;
+ /* This takes care of TIMER1B which is the only choice for Voice TAPI system */
+ unsigned int offset = TIMER2A;
+
+ /*
+ * Pick up a free timer.
+ */
+ if (TIMER_FLAG_MASK_SIZE(flag) == TIMER_FLAG_16BIT) {
+ mask = 1 << offset;
+ shift = 1;
+ } else {
+ mask = 3 << offset;
+ shift = 2;
+ }
+ for (timer = offset;
+ timer < offset + timer_dev.number_of_timers;
+ timer += shift, mask <<= shift)
+ if (!(timer_dev.occupation & mask)) {
+ timer_dev.occupation |= mask;
+ break;
+ }
+ if (timer >= offset + timer_dev.number_of_timers) {
+ printk("failed![%d]\n", __LINE__);
+ mutex_unlock(&timer_dev.gptu_mutex);
+ return -EINVAL;
+ } else
+ ret = timer;
+ } else {
+ register unsigned int mask;
+
+ /*
+ * Check if the requested timer is free.
+ */
+ mask = (TIMER_FLAG_MASK_SIZE(flag) == TIMER_FLAG_16BIT ? 1 : 3) << timer;
+ if ((timer_dev.occupation & mask)) {
+ printk("failed![%d] mask %#x, timer_dev.occupation %#x\n",
+ __LINE__, mask, timer_dev.occupation);
+ mutex_unlock(&timer_dev.gptu_mutex);
+ return -EBUSY;
+ } else {
+ timer_dev.occupation |= mask;
+ ret = 0;
+ }
+ }
+
+ /*
+ * Prepare control register value.
+ */
+ switch (TIMER_FLAG_MASK_EDGE(flag)) {
+ default:
+ case TIMER_FLAG_NONE_EDGE:
+ con_reg = GPTU_CON_EDGE_SET(0x00);
+ break;
+ case TIMER_FLAG_RISE_EDGE:
+ con_reg = GPTU_CON_EDGE_SET(0x01);
+ break;
+ case TIMER_FLAG_FALL_EDGE:
+ con_reg = GPTU_CON_EDGE_SET(0x02);
+ break;
+ case TIMER_FLAG_ANY_EDGE:
+ con_reg = GPTU_CON_EDGE_SET(0x03);
+ break;
+ }
+ if (TIMER_FLAG_MASK_TYPE(flag) == TIMER_FLAG_TIMER)
+ con_reg |=
+ TIMER_FLAG_MASK_SRC(flag) ==
+ TIMER_FLAG_EXT_SRC ? GPTU_CON_SRC_EXT_SET(1) :
+ GPTU_CON_SRC_EXT_SET(0);
+ else
+ con_reg |=
+ TIMER_FLAG_MASK_SRC(flag) ==
+ TIMER_FLAG_EXT_SRC ? GPTU_CON_SRC_EG_SET(1) :
+ GPTU_CON_SRC_EG_SET(0);
+ con_reg |=
+ TIMER_FLAG_MASK_SYNC(flag) ==
+ TIMER_FLAG_UNSYNC ? GPTU_CON_SYNC_SET(0) :
+ GPTU_CON_SYNC_SET(1);
+ con_reg |=
+ TIMER_FLAG_MASK_INVERT(flag) ==
+ TIMER_FLAG_REAL ? GPTU_CON_INV_SET(0) : GPTU_CON_INV_SET(1);
+ con_reg |=
+ TIMER_FLAG_MASK_SIZE(flag) ==
+ TIMER_FLAG_16BIT ? GPTU_CON_EXT_SET(0) :
+ GPTU_CON_EXT_SET(1);
+ con_reg |=
+ TIMER_FLAG_MASK_STOP(flag) ==
+ TIMER_FLAG_ONCE ? GPTU_CON_STP_SET(1) : GPTU_CON_STP_SET(0);
+ con_reg |=
+ TIMER_FLAG_MASK_TYPE(flag) ==
+ TIMER_FLAG_TIMER ? GPTU_CON_CNT_SET(0) :
+ GPTU_CON_CNT_SET(1);
+ con_reg |=
+ TIMER_FLAG_MASK_DIR(flag) ==
+ TIMER_FLAG_UP ? GPTU_CON_DIR_SET(1) : GPTU_CON_DIR_SET(0);
+
+ /*
+ * Fill up running data.
+ */
+ timer_dev.timer[timer - FIRST_TIMER].flag = flag;
+ timer_dev.timer[timer - FIRST_TIMER].arg1 = arg1;
+ timer_dev.timer[timer - FIRST_TIMER].arg2 = arg2;
+ if (TIMER_FLAG_MASK_SIZE(flag) != TIMER_FLAG_16BIT)
+ timer_dev.timer[timer - FIRST_TIMER + 1].flag = flag;
+
+ /*
+ * Enable GPTU module.
+ */
+ if (!timer_dev.f_gptu_on) {
+ lq_enable_gptu();
+ timer_dev.f_gptu_on = 1;
+ }
+
+ /*
+ * Enable IRQ.
+ */
+ if (TIMER_FLAG_MASK_HANDLE(flag) != TIMER_FLAG_NO_HANDLE) {
+ if (TIMER_FLAG_MASK_HANDLE(flag) == TIMER_FLAG_SIGNAL)
+ timer_dev.timer[timer - FIRST_TIMER].arg1 =
+ (unsigned long) find_task_by_vpid((int) arg1);
+
+ irnen_reg = 1 << (timer - FIRST_TIMER);
+
+ if (TIMER_FLAG_MASK_HANDLE(flag) == TIMER_FLAG_SIGNAL
+ || (TIMER_FLAG_MASK_HANDLE(flag) ==
+ TIMER_FLAG_CALLBACK_IN_IRQ
+ && timer_dev.timer[timer - FIRST_TIMER].arg1)) {
+ enable_irq(timer_dev.timer[timer - FIRST_TIMER].irq);
+ timer_dev.timer[timer - FIRST_TIMER].f_irq_on = 1;
+ }
+ } else
+ irnen_reg = 0;
+
+ /*
+ * Write config register, reload value and enable interrupt.
+ */
+ n = timer >> 1;
+ X = timer & 0x01;
+ *LQ_GPTU_CON(n, X) = con_reg;
+ *LQ_GPTU_RELOAD(n, X) = value;
+ /* printk("reload value = %d\n", (u32)value); */
+ *LQ_GPTU_IRNEN |= irnen_reg;
+
+ mutex_unlock(&timer_dev.gptu_mutex);
+ printk("successful!\n");
+ return ret;
+}
+EXPORT_SYMBOL(lq_request_timer);
+
+int lq_free_timer(unsigned int timer)
+{
+ unsigned int flag;
+ unsigned int mask;
+ int n, X;
+
+ if (!timer_dev.f_gptu_on)
+ return -EINVAL;
+
+ if (timer < FIRST_TIMER || timer >= FIRST_TIMER + timer_dev.number_of_timers)
+ return -EINVAL;
+
+ mutex_lock(&timer_dev.gptu_mutex);
+
+ flag = timer_dev.timer[timer - FIRST_TIMER].flag;
+ if (TIMER_FLAG_MASK_SIZE(flag) != TIMER_FLAG_16BIT)
+ timer &= ~0x01;
+
+ mask = (TIMER_FLAG_MASK_SIZE(flag) == TIMER_FLAG_16BIT ? 1 : 3) << timer;
+ if (((timer_dev.occupation & mask) ^ mask)) {
+ mutex_unlock(&timer_dev.gptu_mutex);
+ return -EINVAL;
+ }
+
+ n = timer >> 1;
+ X = timer & 0x01;
+
+ if (GPTU_CON_EN(n, X))
+ *LQ_GPTU_RUN(n, X) = GPTU_RUN_CEN_SET(1);
+
+ *LQ_GPTU_IRNEN &= ~GPTU_IRNEN_TC_SET(n, X, 1);
+ *LQ_GPTU_IRNCR |= GPTU_IRNCR_TC_SET(n, X, 1);
+
+ if (timer_dev.timer[timer - FIRST_TIMER].f_irq_on) {
+ disable_irq(timer_dev.timer[timer - FIRST_TIMER].irq);
+ timer_dev.timer[timer - FIRST_TIMER].f_irq_on = 0;
+ }
+
+ timer_dev.occupation &= ~mask;
+ if (!timer_dev.occupation && timer_dev.f_gptu_on) {
+ lq_disable_gptu();
+ timer_dev.f_gptu_on = 0;
+ }
+
+ mutex_unlock(&timer_dev.gptu_mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL(lq_free_timer);
+
+int lq_start_timer(unsigned int timer, int is_resume)
+{
+ unsigned int flag;
+ unsigned int mask;
+ int n, X;
+
+ if (!timer_dev.f_gptu_on)
+ return -EINVAL;
+
+ if (timer < FIRST_TIMER || timer >= FIRST_TIMER + timer_dev.number_of_timers)
+ return -EINVAL;
+
+ mutex_lock(&timer_dev.gptu_mutex);
+
+ flag = timer_dev.timer[timer - FIRST_TIMER].flag;
+ if (TIMER_FLAG_MASK_SIZE(flag) != TIMER_FLAG_16BIT)
+ timer &= ~0x01;
+
+ mask = (TIMER_FLAG_MASK_SIZE(flag) ==
+ TIMER_FLAG_16BIT ? 1 : 3) << timer;
+ if (((timer_dev.occupation & mask) ^ mask)) {
+ mutex_unlock(&timer_dev.gptu_mutex);
+ return -EINVAL;
+ }
+
+ n = timer >> 1;
+ X = timer & 0x01;
+
+ *LQ_GPTU_RUN(n, X) = GPTU_RUN_RL_SET(!is_resume) | GPTU_RUN_SEN_SET(1);
+
+ mutex_unlock(&timer_dev.gptu_mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL(lq_start_timer);
+
+int lq_stop_timer(unsigned int timer)
+{
+ unsigned int flag;
+ unsigned int mask;
+ int n, X;
+
+ if (!timer_dev.f_gptu_on)
+ return -EINVAL;
+
+ if (timer < FIRST_TIMER
+ || timer >= FIRST_TIMER + timer_dev.number_of_timers)
+ return -EINVAL;
+
+ mutex_lock(&timer_dev.gptu_mutex);
+
+ flag = timer_dev.timer[timer - FIRST_TIMER].flag;
+ if (TIMER_FLAG_MASK_SIZE(flag) != TIMER_FLAG_16BIT)
+ timer &= ~0x01;
+
+ mask = (TIMER_FLAG_MASK_SIZE(flag) == TIMER_FLAG_16BIT ? 1 : 3) << timer;
+ if (((timer_dev.occupation & mask) ^ mask)) {
+ mutex_unlock(&timer_dev.gptu_mutex);
+ return -EINVAL;
+ }
+
+ n = timer >> 1;
+ X = timer & 0x01;
+
+ *LQ_GPTU_RUN(n, X) = GPTU_RUN_CEN_SET(1);
+
+ mutex_unlock(&timer_dev.gptu_mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL(lq_stop_timer);
+
+int lq_reset_counter_flags(u32 timer, u32 flags)
+{
+ unsigned int oflag;
+ unsigned int mask, con_reg;
+ int n, X;
+
+ if (!timer_dev.f_gptu_on)
+ return -EINVAL;
+
+ if (timer < FIRST_TIMER || timer >= FIRST_TIMER + timer_dev.number_of_timers)
+ return -EINVAL;
+
+ mutex_lock(&timer_dev.gptu_mutex);
+
+ oflag = timer_dev.timer[timer - FIRST_TIMER].flag;
+ if (TIMER_FLAG_MASK_SIZE(oflag) != TIMER_FLAG_16BIT)
+ timer &= ~0x01;
+
+ mask = (TIMER_FLAG_MASK_SIZE(oflag) == TIMER_FLAG_16BIT ? 1 : 3) << timer;
+ if (((timer_dev.occupation & mask) ^ mask)) {
+ mutex_unlock(&timer_dev.gptu_mutex);
+ return -EINVAL;
+ }
+
+ switch (TIMER_FLAG_MASK_EDGE(flags)) {
+ default:
+ case TIMER_FLAG_NONE_EDGE:
+ con_reg = GPTU_CON_EDGE_SET(0x00);
+ break;
+ case TIMER_FLAG_RISE_EDGE:
+ con_reg = GPTU_CON_EDGE_SET(0x01);
+ break;
+ case TIMER_FLAG_FALL_EDGE:
+ con_reg = GPTU_CON_EDGE_SET(0x02);
+ break;
+ case TIMER_FLAG_ANY_EDGE:
+ con_reg = GPTU_CON_EDGE_SET(0x03);
+ break;
+ }
+ if (TIMER_FLAG_MASK_TYPE(flags) == TIMER_FLAG_TIMER)
+ con_reg |= TIMER_FLAG_MASK_SRC(flags) == TIMER_FLAG_EXT_SRC ? GPTU_CON_SRC_EXT_SET(1) : GPTU_CON_SRC_EXT_SET(0);
+ else
+ con_reg |= TIMER_FLAG_MASK_SRC(flags) == TIMER_FLAG_EXT_SRC ? GPTU_CON_SRC_EG_SET(1) : GPTU_CON_SRC_EG_SET(0);
+ con_reg |= TIMER_FLAG_MASK_SYNC(flags) == TIMER_FLAG_UNSYNC ? GPTU_CON_SYNC_SET(0) : GPTU_CON_SYNC_SET(1);
+ con_reg |= TIMER_FLAG_MASK_INVERT(flags) == TIMER_FLAG_REAL ? GPTU_CON_INV_SET(0) : GPTU_CON_INV_SET(1);
+ con_reg |= TIMER_FLAG_MASK_SIZE(flags) == TIMER_FLAG_16BIT ? GPTU_CON_EXT_SET(0) : GPTU_CON_EXT_SET(1);
+ con_reg |= TIMER_FLAG_MASK_STOP(flags) == TIMER_FLAG_ONCE ? GPTU_CON_STP_SET(1) : GPTU_CON_STP_SET(0);
+ con_reg |= TIMER_FLAG_MASK_TYPE(flags) == TIMER_FLAG_TIMER ? GPTU_CON_CNT_SET(0) : GPTU_CON_CNT_SET(1);
+ con_reg |= TIMER_FLAG_MASK_DIR(flags) == TIMER_FLAG_UP ? GPTU_CON_DIR_SET(1) : GPTU_CON_DIR_SET(0);
+
+ timer_dev.timer[timer - FIRST_TIMER].flag = flags;
+ if (TIMER_FLAG_MASK_SIZE(flags) != TIMER_FLAG_16BIT)
+ timer_dev.timer[timer - FIRST_TIMER + 1].flag = flags;
+
+ n = timer >> 1;
+ X = timer & 0x01;
+
+ *LQ_GPTU_CON(n, X) = con_reg;
+ smp_wmb();
+ printk(KERN_INFO "[%s]: counter%d oflags %#x, nflags %#x, GPTU_CON %#x\n", __func__, timer, oflag, flags, *LQ_GPTU_CON(n, X));
+ mutex_unlock(&timer_dev.gptu_mutex);
+ return 0;
+}
+EXPORT_SYMBOL(lq_reset_counter_flags);
+
+int lq_get_count_value(unsigned int timer, unsigned long *value)
+{
+ unsigned int flag;
+ unsigned int mask;
+ int n, X;
+
+ if (!timer_dev.f_gptu_on)
+ return -EINVAL;
+
+ if (timer < FIRST_TIMER
+ || timer >= FIRST_TIMER + timer_dev.number_of_timers)
+ return -EINVAL;
+
+ mutex_lock(&timer_dev.gptu_mutex);
+
+ flag = timer_dev.timer[timer - FIRST_TIMER].flag;
+ if (TIMER_FLAG_MASK_SIZE(flag) != TIMER_FLAG_16BIT)
+ timer &= ~0x01;
+
+ mask = (TIMER_FLAG_MASK_SIZE(flag) == TIMER_FLAG_16BIT ? 1 : 3) << timer;
+ if (((timer_dev.occupation & mask) ^ mask)) {
+ mutex_unlock(&timer_dev.gptu_mutex);
+ return -EINVAL;
+ }
+
+ n = timer >> 1;
+ X = timer & 0x01;
+
+ *value = *LQ_GPTU_COUNT(n, X);
+
+ mutex_unlock(&timer_dev.gptu_mutex);
+
+ return 0;
+}
+EXPORT_SYMBOL(lq_get_count_value);
+
+u32 lq_cal_divider(unsigned long freq)
+{
+ u64 module_freq, fpi = ltq_get_fpi_bus_clock(2);
+ u32 clock_divider = 1;
+ module_freq = fpi * 1000;
+ do_div(module_freq, clock_divider * freq);
+ return module_freq;
+}
+EXPORT_SYMBOL(lq_cal_divider);
+
+int lq_set_timer(unsigned int timer, unsigned int freq, int is_cyclic,
+ int is_ext_src, unsigned int handle_flag, unsigned long arg1,
+ unsigned long arg2)
+{
+ unsigned long divider;
+ unsigned int flag;
+
+ divider = lq_cal_divider(freq);
+ if (divider == 0)
+ return -EINVAL;
+ flag = ((divider & ~0xFFFF) ? TIMER_FLAG_32BIT : TIMER_FLAG_16BIT)
+ | (is_cyclic ? TIMER_FLAG_CYCLIC : TIMER_FLAG_ONCE)
+ | (is_ext_src ? TIMER_FLAG_EXT_SRC : TIMER_FLAG_INT_SRC)
+ | TIMER_FLAG_TIMER | TIMER_FLAG_DOWN
+ | TIMER_FLAG_MASK_HANDLE(handle_flag);
+
+ printk(KERN_INFO "lq_set_timer(%d, %d), divider = %lu\n",
+ timer, freq, divider);
+ return lq_request_timer(timer, flag, divider, arg1, arg2);
+}
+EXPORT_SYMBOL(lq_set_timer);
+
+int lq_set_counter(unsigned int timer, unsigned int flag, u32 reload,
+ unsigned long arg1, unsigned long arg2)
+{
+ printk(KERN_INFO "lq_set_counter(%d, %#x, %d)\n", timer, flag, reload);
+ return lq_request_timer(timer, flag, reload, arg1, arg2);
+}
+EXPORT_SYMBOL(lq_set_counter);
+
+static long gptu_ioctl(struct file *file, unsigned int cmd,
+ unsigned long arg)
+{
+ int ret;
+ struct gptu_ioctl_param param;
+
+ if (!access_ok(VERIFY_READ, arg, sizeof(struct gptu_ioctl_param)))
+ return -EFAULT;
+ copy_from_user(&param, (void *) arg, sizeof(param));
+
+ if ((((cmd == GPTU_REQUEST_TIMER || cmd == GPTU_SET_TIMER
+ || GPTU_SET_COUNTER) && param.timer < 2)
+ || cmd == GPTU_GET_COUNT_VALUE || cmd == GPTU_CALCULATE_DIVIDER)
+ && !access_ok(VERIFY_WRITE, arg,
+ sizeof(struct gptu_ioctl_param)))
+ return -EFAULT;
+
+ switch (cmd) {
+ case GPTU_REQUEST_TIMER:
+ ret = lq_request_timer(param.timer, param.flag, param.value,
+ (unsigned long) param.pid,
+ (unsigned long) param.sig);
+ if (ret > 0) {
+ copy_to_user(&((struct gptu_ioctl_param *) arg)->
+ timer, &ret, sizeof(&ret));
+ ret = 0;
+ }
+ break;
+ case GPTU_FREE_TIMER:
+ ret = lq_free_timer(param.timer);
+ break;
+ case GPTU_START_TIMER:
+ ret = lq_start_timer(param.timer, param.flag);
+ break;
+ case GPTU_STOP_TIMER:
+ ret = lq_stop_timer(param.timer);
+ break;
+ case GPTU_GET_COUNT_VALUE:
+ ret = lq_get_count_value(param.timer, &param.value);
+ if (!ret)
+ copy_to_user(&((struct gptu_ioctl_param *) arg)->
+ value, &param.value,
+ sizeof(param.value));
+ break;
+ case GPTU_CALCULATE_DIVIDER:
+ param.value = lq_cal_divider(param.value);
+ if (param.value == 0)
+ ret = -EINVAL;
+ else {
+ copy_to_user(&((struct gptu_ioctl_param *) arg)->
+ value, &param.value,
+ sizeof(param.value));
+ ret = 0;
+ }
+ break;
+ case GPTU_SET_TIMER:
+ ret = lq_set_timer(param.timer, param.value,
+ TIMER_FLAG_MASK_STOP(param.flag) !=
+ TIMER_FLAG_ONCE ? 1 : 0,
+ TIMER_FLAG_MASK_SRC(param.flag) ==
+ TIMER_FLAG_EXT_SRC ? 1 : 0,
+ TIMER_FLAG_MASK_HANDLE(param.flag) ==
+ TIMER_FLAG_SIGNAL ? TIMER_FLAG_SIGNAL :
+ TIMER_FLAG_NO_HANDLE,
+ (unsigned long) param.pid,
+ (unsigned long) param.sig);
+ if (ret > 0) {
+ copy_to_user(&((struct gptu_ioctl_param *) arg)->
+ timer, &ret, sizeof(&ret));
+ ret = 0;
+ }
+ break;
+ case GPTU_SET_COUNTER:
+ lq_set_counter(param.timer, param.flag, param.value, 0, 0);
+ if (ret > 0) {
+ copy_to_user(&((struct gptu_ioctl_param *) arg)->
+ timer, &ret, sizeof(&ret));
+ ret = 0;
+ }
+ break;
+ default:
+ ret = -ENOTTY;
+ }
+
+ return ret;
+}
+
+static int gptu_open(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+static int gptu_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+int __init lq_gptu_init(void)
+{
+ int ret;
+ unsigned int i;
+
+ ltq_w32(0, LQ_GPTU_IRNEN);
+ ltq_w32(0xfff, LQ_GPTU_IRNCR);
+
+ memset(&timer_dev, 0, sizeof(timer_dev));
+ mutex_init(&timer_dev.gptu_mutex);
+
+ lq_enable_gptu();
+ timer_dev.number_of_timers = GPTU_ID_CFG * 2;
+ lq_disable_gptu();
+ if (timer_dev.number_of_timers > MAX_NUM_OF_32BIT_TIMER_BLOCKS * 2)
+ timer_dev.number_of_timers = MAX_NUM_OF_32BIT_TIMER_BLOCKS * 2;
+ printk(KERN_INFO "gptu: totally %d 16-bit timers/counters\n", timer_dev.number_of_timers);
+
+ ret = misc_register(&gptu_miscdev);
+ if (ret) {
+ printk(KERN_ERR "gptu: can't misc_register, get error %d\n", -ret);
+ return ret;
+ } else {
+ printk(KERN_INFO "gptu: misc_register on minor %d\n", gptu_miscdev.minor);
+ }
+
+ for (i = 0; i < timer_dev.number_of_timers; i++) {
+ ret = request_irq(TIMER_INTERRUPT + i, timer_irq_handler, IRQF_TIMER, gptu_miscdev.name, &timer_dev.timer[i]);
+ if (ret) {
+ for (; i >= 0; i--)
+ free_irq(TIMER_INTERRUPT + i, &timer_dev.timer[i]);
+ misc_deregister(&gptu_miscdev);
+ printk(KERN_ERR "gptu: failed in requesting irq (%d), get error %d\n", i, -ret);
+ return ret;
+ } else {
+ timer_dev.timer[i].irq = TIMER_INTERRUPT + i;
+ disable_irq(timer_dev.timer[i].irq);
+ printk(KERN_INFO "gptu: succeeded to request irq %d\n", timer_dev.timer[i].irq);
+ }
+ }
+
+ return 0;
+}
+
+void __exit lq_gptu_exit(void)
+{
+ unsigned int i;
+
+ for (i = 0; i < timer_dev.number_of_timers; i++) {
+ if (timer_dev.timer[i].f_irq_on)
+ disable_irq(timer_dev.timer[i].irq);
+ free_irq(timer_dev.timer[i].irq, &timer_dev.timer[i]);
+ }
+ lq_disable_gptu();
+ misc_deregister(&gptu_miscdev);
+}
+
+module_init(lq_gptu_init);
+module_exit(lq_gptu_exit);
--- /dev/null
+++ b/arch/mips/include/asm/mach-lantiq/lantiq_timer.h
@@ -0,0 +1,155 @@
+#ifndef __DANUBE_GPTU_DEV_H__2005_07_26__10_19__
+#define __DANUBE_GPTU_DEV_H__2005_07_26__10_19__
+
+
+/******************************************************************************
+ Copyright (c) 2002, Infineon Technologies. All rights reserved.
+
+ No Warranty
+ Because the program is licensed free of charge, there is no warranty for
+ the program, to the extent permitted by applicable law. Except when
+ otherwise stated in writing the copyright holders and/or other parties
+ provide the program "as is" without warranty of any kind, either
+ expressed or implied, including, but not limited to, the implied
+ warranties of merchantability and fitness for a particular purpose. The
+ entire risk as to the quality and performance of the program is with
+ you. should the program prove defective, you assume the cost of all
+ necessary servicing, repair or correction.
+
+ In no event unless required by applicable law or agreed to in writing
+ will any copyright holder, or any other party who may modify and/or
+ redistribute the program as permitted above, be liable to you for
+ damages, including any general, special, incidental or consequential
+ damages arising out of the use or inability to use the program
+ (including but not limited to loss of data or data being rendered
+ inaccurate or losses sustained by you or third parties or a failure of
+ the program to operate with any other programs), even if such holder or
+ other party has been advised of the possibility of such damages.
+******************************************************************************/
+
+
+/*
+ * ####################################
+ * Definition
+ * ####################################
+ */
+
+/*
+ * Available Timer/Counter Index
+ */
+#define TIMER(n, X) (n * 2 + (X ? 1 : 0))
+#define TIMER_ANY 0x00
+#define TIMER1A TIMER(1, 0)
+#define TIMER1B TIMER(1, 1)
+#define TIMER2A TIMER(2, 0)
+#define TIMER2B TIMER(2, 1)
+#define TIMER3A TIMER(3, 0)
+#define TIMER3B TIMER(3, 1)
+
+/*
+ * Flag of Timer/Counter
+ * These flags specify the way in which timer is configured.
+ */
+/* Bit size of timer/counter. */
+#define TIMER_FLAG_16BIT 0x0000
+#define TIMER_FLAG_32BIT 0x0001
+/* Switch between timer and counter. */
+#define TIMER_FLAG_TIMER 0x0000
+#define TIMER_FLAG_COUNTER 0x0002
+/* Stop or continue when overflowing/underflowing. */
+#define TIMER_FLAG_ONCE 0x0000
+#define TIMER_FLAG_CYCLIC 0x0004
+/* Count up or counter down. */
+#define TIMER_FLAG_UP 0x0000
+#define TIMER_FLAG_DOWN 0x0008
+/* Count on specific level or edge. */
+#define TIMER_FLAG_HIGH_LEVEL_SENSITIVE 0x0000
+#define TIMER_FLAG_LOW_LEVEL_SENSITIVE 0x0040
+#define TIMER_FLAG_RISE_EDGE 0x0010
+#define TIMER_FLAG_FALL_EDGE 0x0020
+#define TIMER_FLAG_ANY_EDGE 0x0030
+/* Signal is syncronous to module clock or not. */
+#define TIMER_FLAG_UNSYNC 0x0000
+#define TIMER_FLAG_SYNC 0x0080
+/* Different interrupt handle type. */
+#define TIMER_FLAG_NO_HANDLE 0x0000
+#if defined(__KERNEL__)
+ #define TIMER_FLAG_CALLBACK_IN_IRQ 0x0100
+#endif // defined(__KERNEL__)
+#define TIMER_FLAG_SIGNAL 0x0300
+/* Internal clock source or external clock source */
+#define TIMER_FLAG_INT_SRC 0x0000
+#define TIMER_FLAG_EXT_SRC 0x1000
+
+
+/*
+ * ioctl Command
+ */
+#define GPTU_REQUEST_TIMER 0x01 /* General method to setup timer/counter. */
+#define GPTU_FREE_TIMER 0x02 /* Free timer/counter. */
+#define GPTU_START_TIMER 0x03 /* Start or resume timer/counter. */
+#define GPTU_STOP_TIMER 0x04 /* Suspend timer/counter. */
+#define GPTU_GET_COUNT_VALUE 0x05 /* Get current count value. */
+#define GPTU_CALCULATE_DIVIDER 0x06 /* Calculate timer divider from given freq.*/
+#define GPTU_SET_TIMER 0x07 /* Simplified method to setup timer. */
+#define GPTU_SET_COUNTER 0x08 /* Simplified method to setup counter. */
+
+/*
+ * Data Type Used to Call ioctl
+ */
+struct gptu_ioctl_param {
+ unsigned int timer; /* In command GPTU_REQUEST_TIMER, GPTU_SET_TIMER, and *
+ * GPTU_SET_COUNTER, this field is ID of expected *
+ * timer/counter. If it's zero, a timer/counter would *
+ * be dynamically allocated and ID would be stored in *
+ * this field. *
+ * In command GPTU_GET_COUNT_VALUE, this field is *
+ * ignored. *
+ * In other command, this field is ID of timer/counter *
+ * allocated. */
+ unsigned int flag; /* In command GPTU_REQUEST_TIMER, GPTU_SET_TIMER, and *
+ * GPTU_SET_COUNTER, this field contains flags to *
+ * specify how to configure timer/counter. *
+ * In command GPTU_START_TIMER, zero indicate start *
+ * and non-zero indicate resume timer/counter. *
+ * In other command, this field is ignored. */
+ unsigned long value; /* In command GPTU_REQUEST_TIMER, this field contains *
+ * init/reload value. *
+ * In command GPTU_SET_TIMER, this field contains *
+ * frequency (0.001Hz) of timer. *
+ * In command GPTU_GET_COUNT_VALUE, current count *
+ * value would be stored in this field. *
+ * In command GPTU_CALCULATE_DIVIDER, this field *
+ * contains frequency wanted, and after calculation, *
+ * divider would be stored in this field to overwrite *
+ * the frequency. *
+ * In other command, this field is ignored. */
+ int pid; /* In command GPTU_REQUEST_TIMER and GPTU_SET_TIMER, *
+ * if signal is required, this field contains process *
+ * ID to which signal would be sent. *
+ * In other command, this field is ignored. */
+ int sig; /* In command GPTU_REQUEST_TIMER and GPTU_SET_TIMER, *
+ * if signal is required, this field contains signal *
+ * number which would be sent. *
+ * In other command, this field is ignored. */
+};
+
+/*
+ * ####################################
+ * Data Type
+ * ####################################
+ */
+typedef void (*timer_callback)(unsigned long arg);
+
+extern int lq_request_timer(unsigned int, unsigned int, unsigned long, unsigned long, unsigned long);
+extern int lq_free_timer(unsigned int);
+extern int lq_start_timer(unsigned int, int);
+extern int lq_stop_timer(unsigned int);
+extern int lq_reset_counter_flags(u32 timer, u32 flags);
+extern int lq_get_count_value(unsigned int, unsigned long *);
+extern u32 lq_cal_divider(unsigned long);
+extern int lq_set_timer(unsigned int, unsigned int, int, int, unsigned int, unsigned long, unsigned long);
+extern int lq_set_counter(unsigned int timer, unsigned int flag,
+ u32 reload, unsigned long arg1, unsigned long arg2);
+
+#endif /* __DANUBE_GPTU_DEV_H__2005_07_26__10_19__ */
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -1,4 +1,4 @@
-obj-y := pmu.o ebu.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o
+obj-y := pmu.o ebu.o reset.o gpio.o gpio_stp.o gpio_ebu.o devices.o dma.o timer.o
obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o setup-xway.o
obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o setup-ase.o

File diff suppressed because it is too large Load Diff

View File

@ -1,95 +0,0 @@
--- /dev/null
+++ b/arch/mips/include/asm/mach-lantiq/dev-leds-gpio.h
@@ -0,0 +1,21 @@
+/*
+ * Lantiq GPIO LED device support
+ *
+ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * 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.
+ */
+
+#ifndef _LANTIQ_DEV_LEDS_GPIO_H
+#define _LANTIQ_DEV_LEDS_GPIO_H
+
+#include <linux/leds.h>
+
+void ltq_add_device_leds_gpio(int id,
+ unsigned num_leds,
+ struct gpio_led *leds) __init;
+
+#endif /* _LANTIQ_DEV_LEDS_GPIO_H */
--- /dev/null
+++ b/arch/mips/lantiq/dev-leds-gpio.c
@@ -0,0 +1,57 @@
+/*
+ * Lantiq GPIO LED device support
+ *
+ * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org>
+ * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org>
+ *
+ * Parts of this file are based on Atheros' 2.6.15 BSP
+ *
+ * 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.
+ */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+
+#include "dev-leds-gpio.h"
+
+void __init ltq_add_device_leds_gpio(int id, unsigned num_leds,
+ struct gpio_led *leds)
+{
+ struct platform_device *pdev;
+ struct gpio_led_platform_data pdata;
+ struct gpio_led *p;
+ int err;
+
+ p = kmalloc(num_leds * sizeof(*p), GFP_KERNEL);
+ if (!p)
+ return;
+
+ memcpy(p, leds, num_leds * sizeof(*p));
+
+ pdev = platform_device_alloc("leds-gpio", id);
+ if (!pdev)
+ goto err_free_leds;
+
+ memset(&pdata, 0, sizeof(pdata));
+ pdata.num_leds = num_leds;
+ pdata.leds = p;
+
+ err = platform_device_add_data(pdev, &pdata, sizeof(pdata));
+ if (err)
+ goto err_put_pdev;
+
+ err = platform_device_add(pdev);
+ if (err)
+ goto err_put_pdev;
+
+ return;
+
+err_put_pdev:
+ platform_device_put(pdev);
+
+err_free_leds:
+ kfree(p);
+}
--- a/arch/mips/lantiq/Makefile
+++ b/arch/mips/lantiq/Makefile
@@ -4,7 +4,7 @@
# under the terms of the GNU General Public License version 2 as published
# by the Free Software Foundation.
-obj-y := irq.o setup.o clk.o prom.o devices.o dev-gpio-buttons.o
+obj-y := irq.o setup.o clk.o prom.o devices.o dev-gpio-buttons.o dev-leds-gpio.o
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o

View File

@ -1,20 +0,0 @@
--- a/arch/mips/lantiq/xway/gpio_ebu.c
+++ b/arch/mips/lantiq/xway/gpio_ebu.c
@@ -63,7 +63,6 @@ static struct gpio_chip ltq_ebu_chip = {
.set = ltq_ebu_set,
.base = 72,
.ngpio = 16,
- .can_sleep = 1,
.owner = THIS_MODULE,
};
--- a/arch/mips/lantiq/xway/gpio_stp.c
+++ b/arch/mips/lantiq/xway/gpio_stp.c
@@ -72,7 +72,6 @@ static struct gpio_chip ltq_stp_chip = {
.set = ltq_stp_set,
.base = 48,
.ngpio = 24,
- .can_sleep = 1,
.owner = THIS_MODULE,
};

View File

@ -1,111 +0,0 @@
--- a/arch/mips/lantiq/machtypes.h
+++ b/arch/mips/lantiq/machtypes.h
@@ -34,6 +34,9 @@ enum lantiq_mach_type {
LANTIQ_MACH_ARV752DPW, /* Arcor easybox a802 */
LANTIQ_MACH_ARV752DPW22, /* Arcor easybox a803 */
LANTIQ_MACH_ARV7518PW, /* ASTORIA */
+
+ /* Netgear */
+ LANTIQ_MACH_DGN3500B, /* Netgear DGN3500 */
};
#endif
--- a/arch/mips/lantiq/xway/Kconfig
+++ b/arch/mips/lantiq/xway/Kconfig
@@ -10,6 +10,10 @@ config LANTIQ_MACH_ARV45XX
bool "ARV45XX"
default y
+config LANTIQ_MACH_NETGEAR
+ bool "Netgear"
+ default y
+
endmenu
endif
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -6,4 +6,5 @@ obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o
obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o
obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o
obj-$(CONFIG_LANTIQ_MACH_ARV45XX) += mach-arv45xx.o
+obj-$(CONFIG_LANTIQ_MACH_NETGEAR) += mach-netgear.o
obj-y += dev-dwc_otg.o
--- a/arch/mips/lantiq/xway/devices.h
+++ b/arch/mips/lantiq/xway/devices.h
@@ -11,6 +11,7 @@
#include "../devices.h"
#include <linux/phy.h>
+#include <linux/spi/spi.h>
extern void ltq_register_gpio(void);
extern void ltq_register_gpio_stp(void);
@@ -18,5 +19,7 @@ extern void ltq_register_ase_asc(void);
extern void ltq_register_etop(struct ltq_eth_data *eth);
extern void ltq_register_gpio_ebu(unsigned int value);
extern void ltq_register_madwifi_eep(unsigned long long addr);
+extern void ltq_register_spi(struct ltq_spi_platform_data *pdata,
+ struct spi_board_info const *info, unsigned n);
#endif
--- /dev/null
+++ b/arch/mips/lantiq/xway/mach-netgear.c
@@ -0,0 +1,57 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/input.h>
+#include <linux/phy.h>
+#include <linux/spi/spi.h>
+
+#include <lantiq_soc.h>
+#include <irq.h>
+
+#include "../machtypes.h"
+#include "devices.h"
+
+static struct ltq_pci_data ltq_pci_data = {
+ .clock = PCI_CLOCK_INT,
+ .gpio = PCI_GNT1 | PCI_REQ1,
+ .irq = {
+ [14] = INT_NUM_IM0_IRL0 + 22,
+ },
+};
+
+static struct ltq_eth_data ltq_eth_data = {
+ .mii_mode = PHY_INTERFACE_MODE_MII,
+};
+
+struct spi_board_info spi_info = {
+ .bus_num = 0,
+ .chip_select = 3,
+ .max_speed_hz = 25000000,
+ .modalias = "mx25l12805d",
+};
+
+struct ltq_spi_platform_data ltq_spi_data = {
+ .num_chipselect = 4,
+};
+
+static void __init dgn3500_init(void)
+{
+ ltq_register_pci(&ltq_pci_data);
+ ltq_register_etop(&ltq_eth_data);
+ ltq_register_spi(&ltq_spi_data, &spi_info, 1);
+}
+
+MIPS_MACHINE(LANTIQ_MACH_DGN3500B,
+ "DGN3500B",
+ "Netgear DGN3500B",
+ dgn3500_init);

View File

@ -1,246 +0,0 @@
--- a/arch/mips/lantiq/xway/Kconfig
+++ b/arch/mips/lantiq/xway/Kconfig
@@ -14,6 +14,11 @@ config LANTIQ_MACH_NETGEAR
bool "Netgear"
default y
+config LANTIQ_MACH_GIGASX76X
+ bool "GIGASX76X"
+ select LTQ_DEV_GPIO_BUTTONS
+ default y
+
endmenu
endif
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -7,4 +7,5 @@ obj-$(CONFIG_LANTIQ_MACH_EASY50712) += m
obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o
obj-$(CONFIG_LANTIQ_MACH_ARV45XX) += mach-arv45xx.o
obj-$(CONFIG_LANTIQ_MACH_NETGEAR) += mach-netgear.o
+obj-$(CONFIG_LANTIQ_MACH_GIGASX76X) += mach-gigasx76x.o
obj-y += dev-dwc_otg.o
--- /dev/null
+++ b/arch/mips/lantiq/xway/mach-gigasx76x.c
@@ -0,0 +1,209 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2011 Andrej Vlašić
+ * Copyright (C) 2011 Luka Perkov
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/gpio.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/input.h>
+#include <linux/ath5k_platform.h>
+#include <linux/pci.h>
+#include <linux/phy.h>
+#include <linux/io.h>
+#include <linux/string.h>
+
+#include <irq.h>
+
+#include <lantiq_soc.h>
+#include <lantiq_platform.h>
+
+#include "devices.h"
+#include "dev-dwc_otg.h"
+#include "../machtypes.h"
+#include "../dev-leds-gpio.h"
+#include "../dev-gpio-buttons.h"
+
+#define UBOOT_ENV_OFFSET 0x010000
+#define UBOOT_ENV_SIZE 0x010000
+
+#ifdef CONFIG_MTD_PARTITIONS
+static struct mtd_partition gigasx76x_partitions[] =
+{
+ {
+ .name = "uboot",
+ .offset = 0x000000,
+ .size = 0x010000,
+ },
+ {
+ .name = "uboot_env",
+ .offset = UBOOT_ENV_OFFSET,
+ .size = UBOOT_ENV_SIZE,
+ },
+ {
+ .name = "linux",
+ .offset = 0x020000,
+ .size = 0x7d0000,
+ },
+ {
+ .name = "board_config",
+ .offset = 0x7f0000,
+ .size = 0x010000,
+ },
+};
+#endif
+
+static struct gpio_led
+gigasx76x_gpio_leds[] __initdata = {
+ { .name = "soc:green:usb", .gpio = 50, },
+ { .name = "soc:green:wlan", .gpio = 51, },
+ { .name = "soc:green:phone2", .gpio = 52, },
+ { .name = "soc:green:phone1", .gpio = 53, },
+ { .name = "soc:green:line", .gpio = 54, },
+ { .name = "soc:green:online", .gpio = 55, },
+ { .name = "soc:green:voip", .gpio = 56, },
+};
+
+static struct gpio_keys_button
+gigasx76x_gpio_keys[] __initdata = {
+ {
+ .desc = "reset",
+ .type = EV_KEY,
+ .code = KEY_RESTART,
+ .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
+ .gpio = 14,
+ .active_low = 1,
+ },
+};
+
+static struct physmap_flash_data gigasx76x_flash_data = {
+#ifdef CONFIG_MTD_PARTITIONS
+ .nr_parts = ARRAY_SIZE(gigasx76x_partitions),
+ .parts = gigasx76x_partitions,
+#endif
+};
+
+static struct ltq_pci_data ltq_pci_data = {
+ .clock = PCI_CLOCK_INT,
+ .gpio = PCI_GNT1 | PCI_REQ1,
+ .irq = { [14] = INT_NUM_IM0_IRL0 + 22, },
+};
+
+static struct ltq_eth_data ltq_eth_data = {
+ .mii_mode = PHY_INTERFACE_MODE_MII,
+};
+
+static char __init *get_uboot_env_var(char *haystack, int haystack_len, char *needle, int needle_len) {
+ int i;
+ for (i = 0; i <= haystack_len - needle_len; i++) {
+ if (memcmp(haystack + i, needle, needle_len) == 0) {
+ return haystack + i + needle_len;
+ }
+ }
+ return NULL;
+}
+
+/*
+ * gigasx76x_parse_hex_* are not uniq. in arm/orion there are also duplicates:
+ * dns323_parse_hex_*
+ * TODO: one day write a patch for this :)
+ */
+static int __init gigasx76x_parse_hex_nibble(char n) {
+ if (n >= '0' && n <= '9')
+ return n - '0';
+
+ if (n >= 'A' && n <= 'F')
+ return n - 'A' + 10;
+
+ if (n >= 'a' && n <= 'f')
+ return n - 'a' + 10;
+
+ return -1;
+}
+
+static int __init gigasx76x_parse_hex_byte(const char *b) {
+ int hi;
+ int lo;
+
+ hi = gigasx76x_parse_hex_nibble(b[0]);
+ lo = gigasx76x_parse_hex_nibble(b[1]);
+
+ if (hi < 0 || lo < 0)
+ return -1;
+
+ return (hi << 4) | lo;
+}
+
+static int __init gigasx76x_register_ethernet(void) {
+ u_int8_t addr[6];
+ int i;
+ char *uboot_env_page;
+ char *mac;
+
+ uboot_env_page = ioremap(LTQ_FLASH_START + UBOOT_ENV_OFFSET, UBOOT_ENV_SIZE);
+ if (!uboot_env_page)
+ return -ENOMEM;
+
+ mac = get_uboot_env_var(uboot_env_page, UBOOT_ENV_SIZE, "\0ethaddr=", 9);
+
+ if (!mac) {
+ goto error_fail;
+ }
+
+ /* Sanity check the string we're looking at */
+ for (i = 0; i < 5; i++) {
+ if (*(mac + (i * 3) + 2) != ':') {
+ goto error_fail;
+ }
+ }
+
+ for (i = 0; i < 6; i++) {
+ int byte;
+ byte = gigasx76x_parse_hex_byte(mac + (i * 3));
+ if (byte < 0) {
+ goto error_fail;
+ }
+ addr[i] = byte;
+ }
+
+ iounmap(uboot_env_page);
+ printk("GIGASX76X: Found ethernet MAC address: ");
+ for (i = 0; i < 6; i++)
+ printk("%.2x%s", addr[i], (i < 5) ? ":" : ".\n");
+
+ memcpy(&ltq_eth_data.mac.sa_data, addr, 6);
+ ltq_register_etop(&ltq_eth_data);
+
+ return 0;
+
+ error_fail:
+ iounmap(uboot_env_page);
+ return -EINVAL;
+}
+
+static void __init gigasx76x_init(void) {
+#define GIGASX76X_USB 29
+#define GIGASX76X_MADWIFI_ADDR 0xb07f0000
+
+ ltq_register_gpio_stp();
+ ltq_register_nor(&gigasx76x_flash_data);
+ ltq_register_pci(&ltq_pci_data);
+ gigasx76x_register_ethernet();
+ xway_register_dwc(GIGASX76X_USB);
+ ltq_register_tapi();
+ ltq_register_madwifi_eep(GIGASX76X_MADWIFI_ADDR);
+ ltq_add_device_leds_gpio(-1, ARRAY_SIZE(gigasx76x_gpio_leds), gigasx76x_gpio_leds);
+ ltq_register_gpio_keys_polled(-1, LTQ_KEYS_POLL_INTERVAL, ARRAY_SIZE(gigasx76x_gpio_keys), gigasx76x_gpio_keys);
+}
+
+MIPS_MACHINE(LANTIQ_MACH_GIGASX76X, "GIGASX76X", "GIGASX76X - Gigaset SX761,SX762,SX763", gigasx76x_init);
--- a/arch/mips/lantiq/machtypes.h
+++ b/arch/mips/lantiq/machtypes.h
@@ -37,6 +37,9 @@ enum lantiq_mach_type {
/* Netgear */
LANTIQ_MACH_DGN3500B, /* Netgear DGN3500 */
+
+ /* Gigaset */
+ LANTIQ_MACH_GIGASX76X, /* Gigaset SX76x */
};
#endif

View File

@ -1,157 +0,0 @@
--- a/arch/mips/lantiq/machtypes.h
+++ b/arch/mips/lantiq/machtypes.h
@@ -40,6 +40,9 @@
/* Gigaset */
LANTIQ_MACH_GIGASX76X, /* Gigaset SX76x */
+
+ /* Buffalo */
+ LANTIQ_MACH_WBMR, /* WBMR-HP-G300H */
};
#endif
--- a/arch/mips/lantiq/xway/Kconfig
+++ b/arch/mips/lantiq/xway/Kconfig
@@ -19,6 +19,11 @@
select LTQ_DEV_GPIO_BUTTONS
default y
+config LANTIQ_MACH_WBMR
+ bool "WBMR-HP-G300H"
+ select LTQ_DEV_GPIO_BUTTONS
+ default y
+
endmenu
endif
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -8,4 +8,5 @@
obj-$(CONFIG_LANTIQ_MACH_ARV45XX) += mach-arv45xx.o
obj-$(CONFIG_LANTIQ_MACH_NETGEAR) += mach-netgear.o
obj-$(CONFIG_LANTIQ_MACH_GIGASX76X) += mach-gigasx76x.o
+obj-$(CONFIG_LANTIQ_MACH_WBMR) += mach-wbmr.o
obj-y += dev-dwc_otg.o
--- /dev/null
+++ b/arch/mips/lantiq/xway/mach-wbmr.c
@@ -0,0 +1,120 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/leds.h>
+#include <linux/gpio.h>
+#include <linux/gpio_buttons.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <linux/input.h>
+
+#include <lantiq_soc.h>
+#include <irq.h>
+
+#include "../machtypes.h"
+#include "devices.h"
+#include "dev-leds-gpio.h"
+#include "dev-dwc_otg.h"
+#include "../dev-gpio-buttons.h"
+
+static struct mtd_partition wbmr_partitions[] =
+{
+ {
+ .name = "uboot",
+ .offset = 0x0,
+ .size = 0x40000,
+ },
+ {
+ .name = "uboot-env",
+ .offset = 0x40000,
+ .size = 0x20000,
+ },
+ {
+ .name = "linux",
+ .offset = 0x60000,
+ .size = 0x1f20000,
+ },
+ {
+ .name = "calibration",
+ .offset = 0x1fe0000,
+ .size = 0x20000,
+ },
+};
+
+static struct physmap_flash_data wbmr_flash_data = {
+ .nr_parts = ARRAY_SIZE(wbmr_partitions),
+ .parts = wbmr_partitions,
+};
+
+static struct gpio_led
+wbmr_leds_gpio[] __initdata = {
+ { .name = "soc:blue:movie", .gpio = 20, .active_low = 1, },
+ { .name = "soc:red:internet", .gpio = 18, .active_low = 1, },
+ { .name = "soc:green:internet", .gpio = 17, .active_low = 1, },
+ { .name = "soc:green:adsl", .gpio = 16, .active_low = 1, },
+ { .name = "soc:green:wlan", .gpio = 15, .active_low = 1, },
+ { .name = "soc:red:security", .gpio = 14, .active_low = 1, },
+ { .name = "soc:green:power", .gpio = 1, .active_low = 1, },
+ { .name = "soc:red:power", .gpio = 5, .active_low = 1, },
+ { .name = "soc:green:usb", .gpio = 28, .active_low = 1, },
+};
+
+static struct gpio_keys_button
+wbmr_gpio_keys[] __initdata = {
+ {
+ .desc = "aoss",
+ .type = EV_KEY,
+ .code = BTN_0,
+ .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
+ .gpio = 0,
+ .active_low = 1,
+ },
+ {
+ .desc = "reset",
+ .type = EV_KEY,
+ .code = BTN_1,
+ .debounce_interval = LTQ_KEYS_DEBOUNCE_INTERVAL,
+ .gpio = 37,
+ .active_low = 1,
+ },
+};
+
+static struct ltq_pci_data ltq_pci_data = {
+ .clock = PCI_CLOCK_INT,
+ .gpio = PCI_GNT1 | PCI_REQ1,
+ .irq = {
+ [14] = INT_NUM_IM0_IRL0 + 22,
+ },
+};
+
+static struct ltq_eth_data ltq_eth_data = {
+ .mii_mode = PHY_INTERFACE_MODE_MII,
+};
+
+static void __init
+wbmr_init(void)
+{
+#define WMBR_BRN_MAC 0x1fd0024
+
+ ltq_add_device_leds_gpio(-1, ARRAY_SIZE(wbmr_leds_gpio), wbmr_leds_gpio);
+ ltq_register_gpio_keys_polled(-1, LTQ_KEYS_POLL_INTERVAL, ARRAY_SIZE(wbmr_gpio_keys), wbmr_gpio_keys);
+ ltq_register_nor(&wbmr_flash_data);
+ ltq_register_pci(&ltq_pci_data);
+ memcpy_fromio(&ltq_eth_data.mac.sa_data,
+ (void *)KSEG1ADDR(LTQ_FLASH_START + WMBR_BRN_MAC), 6);
+ ltq_register_etop(&ltq_eth_data);
+ xway_register_dwc(36);
+}
+
+MIPS_MACHINE(LANTIQ_MACH_WBMR,
+ "WBMR",
+ "WBMR",
+ wbmr_init);

View File

@ -1,14 +0,0 @@
--- a/drivers/tty/serial/lantiq.c
+++ b/drivers/tty/serial/lantiq.c
@@ -478,8 +478,10 @@ lqasc_set_termios(struct uart_port *port
spin_unlock_irqrestore(&ltq_asc_lock, flags);
/* Don't rewrite B0 */
- if (tty_termios_baud_rate(new))
+ if (tty_termios_baud_rate(new))
tty_termios_encode_baud_rate(new, baud, baud);
+
+ uart_update_timeout(port, cflag, baud);
}
static const char*

View File

@ -1,26 +0,0 @@
--- a/arch/mips/lantiq/early_printk.c
+++ b/arch/mips/lantiq/early_printk.c
@@ -20,7 +20,12 @@
#endif
#define ASC_BUF 1024
#define LTQ_ASC_FSTAT ((u32 *)(LTQ_ASC_BASE + 0x0048))
-#define LTQ_ASC_TBUF ((u32 *)(LTQ_ASC_BASE + 0x0020))
+#ifdef __BIG_ENDIAN
+#define LTQ_ASC_TBUF ((u8 *)(LTQ_ASC_BASE + 0x0023))
+#else
+#define LTQ_ASC_TBUF ((u8 *)(LTQ_ASC_BASE + 0x0020))
+#endif
+
#define TXMASK 0x3F00
#define TXOFFSET 8
@@ -30,8 +35,6 @@ void prom_putchar(char c)
local_irq_save(flags);
do { } while ((ltq_r32(LTQ_ASC_FSTAT) & TXMASK) >> TXOFFSET);
- if (c == '\n')
- ltq_w32('\r', LTQ_ASC_TBUF);
- ltq_w32(c, LTQ_ASC_TBUF);
+ ltq_w8(c, LTQ_ASC_TBUF);
local_irq_restore(flags);
}

View File

@ -1,43 +0,0 @@
--- /dev/null
+++ b/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
+ */
+
+#ifndef _LTQ_FALCON_H__
+#define _LTQ_FALCON_H__
+
+#ifdef CONFIG_SOC_FALCON
+
+#include <lantiq.h>
+
+/* Chip IDs */
+#define SOC_ID_FALCON 0x01B8
+
+/* SoC Types */
+#define SOC_TYPE_FALCON 0x01
+
+/* ASC0/1 - serial port */
+#define LTQ_ASC0_BASE_ADDR 0x1E100C00
+#define LTQ_ASC1_BASE_ADDR 0x1E100B00
+#define LTQ_ASC_SIZE 0x100
+
+#define LTQ_ASC_TIR(x) (INT_NUM_IM3_IRL0 + (x * 8))
+#define LTQ_ASC_RIR(x) (INT_NUM_IM3_IRL0 + (x * 8) + 1)
+#define LTQ_ASC_EIR(x) (INT_NUM_IM3_IRL0 + (x * 8) + 2)
+
+/* ICU - interrupt control unit */
+#define LTQ_ICU_BASE_ADDR 0x1F880200
+#define LTQ_ICU_SIZE 0x100
+
+/* WDT */
+#define LTQ_WDT_BASE_ADDR 0x1F8803F0
+#define LTQ_WDT_SIZE 0x10
+
+#endif /* CONFIG_SOC_FALCON */
+#endif /* _LTQ_XWAY_H__ */

View File

@ -1,98 +0,0 @@
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
@@ -40,6 +40,15 @@
#define MIPS_CPU_TIMER_IRQ 7
+#ifdef CONFIG_SOC_AMAZON_SE
+#define LTQ_DMA_CH0_INT (INT_NUM_IM3_IRL0)
+#define LTQ_DMA_CH1_INT (INT_NUM_IM3_IRL0 + 1)
+#define LTQ_DMA_CH2_INT (INT_NUM_IM3_IRL0 + 2)
+#define LTQ_DMA_CH3_INT (INT_NUM_IM3_IRL0 + 3)
+#define LTQ_DMA_CH4_INT (INT_NUM_IM3_IRL0 + 4)
+#define LTQ_DMA_CH5_INT (INT_NUM_IM3_IRL0 + 5)
+#define LTQ_DMA_CH6_INT (INT_NUM_IM3_IRL0 + 6)
+#else
#define LTQ_DMA_CH0_INT (INT_NUM_IM2_IRL0)
#define LTQ_DMA_CH1_INT (INT_NUM_IM2_IRL0 + 1)
#define LTQ_DMA_CH2_INT (INT_NUM_IM2_IRL0 + 2)
@@ -47,6 +56,7 @@
#define LTQ_DMA_CH4_INT (INT_NUM_IM2_IRL0 + 4)
#define LTQ_DMA_CH5_INT (INT_NUM_IM2_IRL0 + 5)
#define LTQ_DMA_CH6_INT (INT_NUM_IM2_IRL0 + 6)
+#endif
#define LTQ_DMA_CH7_INT (INT_NUM_IM2_IRL0 + 7)
#define LTQ_DMA_CH8_INT (INT_NUM_IM2_IRL0 + 8)
#define LTQ_DMA_CH9_INT (INT_NUM_IM2_IRL0 + 9)
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
@@ -128,6 +128,11 @@
extern void ltq_pmu_enable(unsigned int module);
extern void ltq_pmu_disable(unsigned int module);
+static inline int ltq_is_ase(void)
+{
+ return (ltq_get_soc_type() == SOC_TYPE_AMAZON_SE);
+}
+
static inline int ltq_is_ar9(void)
{
return (ltq_get_soc_type() == SOC_TYPE_AR9);
--- a/arch/mips/lantiq/xway/mach-easy50601.c
+++ b/arch/mips/lantiq/xway/mach-easy50601.c
@@ -41,9 +41,14 @@
.parts = easy50601_partitions,
};
+static struct ltq_eth_data ltq_eth_data = {
+ .mii_mode = -1, /* use EPHY */
+};
+
static void __init easy50601_init(void)
{
ltq_register_nor(&easy50601_flash_data);
+ ltq_register_etop(&ltq_eth_data);
}
MIPS_MACHINE(LTQ_MACH_EASY50601,
--- a/drivers/net/lantiq_etop.c
+++ b/drivers/net/lantiq_etop.c
@@ -72,7 +72,11 @@
/* use 2 static channels for TX/RX */
#define LTQ_ETOP_TX_CHANNEL 1
+#ifdef CONFIG_SOC_AMAZON_SE
+#define LTQ_ETOP_RX_CHANNEL 5
+#else
#define LTQ_ETOP_RX_CHANNEL 6
+#endif
#define IS_TX(x) (x == LTQ_ETOP_TX_CHANNEL)
#define IS_RX(x) (x == LTQ_ETOP_RX_CHANNEL)
@@ -255,6 +259,9 @@
}
static int
+ltq_etop_mdio_wr(struct mii_bus *bus, int phy_addr, int phy_reg, u16 phy_data);
+
+static int
ltq_etop_hw_init(struct net_device *dev)
{
struct ltq_etop_priv *priv = netdev_priv(dev);
@@ -274,6 +281,16 @@
break;
default:
+ if (ltq_is_ase()) {
+#define PMU_EPHY 0x80
+#define LTQ_CGU_IFCCR 0x0018
+ ltq_pmu_enable(PMU_EPHY);
+ ltq_etop_w32_mask(0, 1, LTQ_ETOP_CFG);
+ ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | (0x1 << 4), LTQ_CGU_IFCCR);
+ ltq_etop_mdio_wr(NULL, 0x8, 0x12, 0xC020);
+ printk("Selected EPHY mode \n");
+ break;
+ }
netdev_err(dev, "unknown mii mode %d\n",
priv->pldata->mii_mode);
return -ENOTSUPP;

View File

@ -1,20 +0,0 @@
--- a/arch/mips/lantiq/irq.c
+++ b/arch/mips/lantiq/irq.c
@@ -132,7 +132,7 @@
static unsigned int ltq_startup_eiu_irq(struct irq_data *d)
{
int i;
- int irq_nr = d->irq - INT_NUM_IRQ0;
+ int irq_nr = d->irq;
ltq_enable_irq(d);
for (i = 0; i < MAX_EIU; i++) {
@@ -156,7 +156,7 @@
static void ltq_shutdown_eiu_irq(struct irq_data *d)
{
int i;
- int irq_nr = d->irq - INT_NUM_IRQ0;
+ int irq_nr = d->irq;
ltq_disable_irq(d);
for (i = 0; i < MAX_EIU; i++) {

View File

@ -1,18 +0,0 @@
--- a/arch/mips/pci/pci-lantiq.c
+++ b/arch/mips/pci/pci-lantiq.c
@@ -171,8 +171,13 @@
u32 temp_buffer;
/* set clock to 33Mhz */
- ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~0xf00000, LTQ_CGU_IFCCR);
- ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | 0x800000, LTQ_CGU_IFCCR);
+ if (ltq_is_ar9()) {
+ ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~0x1f00000, LTQ_CGU_IFCCR);
+ ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | 0xe00000, LTQ_CGU_IFCCR);
+ } else {
+ ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~0xf00000, LTQ_CGU_IFCCR);
+ ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | 0x800000, LTQ_CGU_IFCCR);
+ }
/* external or internal clock ? */
if (conf->clock) {

View File

@ -1,45 +0,0 @@
From 14ea48a5f5702ddc97425cbe520600e187e14e4a Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 11 Aug 2011 13:58:39 +0200
Subject: [PATCH 03/24] MIPS: lantiq: fix watchdogs timeout handling
The enable function was using the global timeout variable for local operations.
This resulted in the value of the global variable being corrupted, thus
breaking the code.
Signed-off-by: John Crispin <blogic@openwrt.org>
Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
Cc: linux-watchdog@vger.kernel.org
Cc: linux-mips@linux-mips.org
---
drivers/watchdog/lantiq_wdt.c | 8 ++++----
1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/watchdog/lantiq_wdt.c b/drivers/watchdog/lantiq_wdt.c
index 7d82ada..102aed0 100644
--- a/drivers/watchdog/lantiq_wdt.c
+++ b/drivers/watchdog/lantiq_wdt.c
@@ -51,16 +51,16 @@ static int ltq_wdt_ok_to_close;
static void
ltq_wdt_enable(void)
{
- ltq_wdt_timeout = ltq_wdt_timeout *
+ unsigned long int timeout = ltq_wdt_timeout *
(ltq_io_region_clk_rate / LTQ_WDT_DIVIDER) + 0x1000;
- if (ltq_wdt_timeout > LTQ_MAX_TIMEOUT)
- ltq_wdt_timeout = LTQ_MAX_TIMEOUT;
+ if (timeout > LTQ_MAX_TIMEOUT)
+ timeout = LTQ_MAX_TIMEOUT;
/* write the first password magic */
ltq_w32(LTQ_WDT_PW1, ltq_wdt_membase + LTQ_WDT_CR);
/* write the second magic plus the configuration and new timeout */
ltq_w32(LTQ_WDT_SR_EN | LTQ_WDT_SR_PWD | LTQ_WDT_SR_CLKDIV |
- LTQ_WDT_PW2 | ltq_wdt_timeout, ltq_wdt_membase + LTQ_WDT_CR);
+ LTQ_WDT_PW2 | timeout, ltq_wdt_membase + LTQ_WDT_CR);
}
static void
--
1.7.5.4

View File

@ -1,47 +0,0 @@
Index: linux-3.0.3/arch/mips/lantiq/prom.c
===================================================================
--- linux-3.0.3.orig/arch/mips/lantiq/prom.c 2011-10-02 15:49:12.000000000 +0200
+++ linux-3.0.3/arch/mips/lantiq/prom.c 2011-10-02 15:50:34.614270672 +0200
@@ -43,6 +43,34 @@
{
}
+#ifdef CONFIG_IMAGE_CMDLINE_HACK
+extern char __image_cmdline[];
+
+static void __init
+prom_init_image_cmdline(void)
+{
+ char *p = __image_cmdline;
+ int replace = 0;
+
+ if (*p == '-') {
+ replace = 1;
+ p++;
+ }
+
+ if (*p == '\0')
+ return;
+
+ if (replace) {
+ strlcpy(arcs_cmdline, p, sizeof(arcs_cmdline));
+ } else {
+ strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline));
+ strlcat(arcs_cmdline, p, sizeof(arcs_cmdline));
+ }
+}
+#else
+static void __init prom_init_image_cmdline(void) { return; }
+#endif
+
static void __init prom_init_cmdline(void)
{
int argc = fw_arg0;
@@ -59,6 +87,7 @@
strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline));
}
}
+ prom_init_image_cmdline();
}
void __iomem *ltq_remap_resource(struct resource *res)

View File

@ -1,14 +0,0 @@
--- a/drivers/tty/serial/lantiq.c
+++ b/drivers/tty/serial/lantiq.c
@@ -478,8 +478,10 @@ lqasc_set_termios(struct uart_port *port
spin_unlock_irqrestore(&ltq_asc_lock, flags);
/* Don't rewrite B0 */
- if (tty_termios_baud_rate(new))
+ if (tty_termios_baud_rate(new))
tty_termios_encode_baud_rate(new, baud, baud);
+
+ uart_update_timeout(port, cflag, baud);
}
static const char*

View File

@ -1,20 +0,0 @@
--- a/arch/mips/lantiq/irq.c
+++ b/arch/mips/lantiq/irq.c
@@ -132,7 +132,7 @@
static unsigned int ltq_startup_eiu_irq(struct irq_data *d)
{
int i;
- int irq_nr = d->irq - INT_NUM_IRQ0;
+ int irq_nr = d->irq;
ltq_enable_irq(d);
for (i = 0; i < MAX_EIU; i++) {
@@ -156,7 +156,7 @@
static void ltq_shutdown_eiu_irq(struct irq_data *d)
{
int i;
- int irq_nr = d->irq - INT_NUM_IRQ0;
+ int irq_nr = d->irq;
ltq_disable_irq(d);
for (i = 0; i < MAX_EIU; i++) {

View File

@ -1,18 +0,0 @@
--- a/arch/mips/pci/pci-lantiq.c
+++ b/arch/mips/pci/pci-lantiq.c
@@ -171,8 +171,13 @@
u32 temp_buffer;
/* set clock to 33Mhz */
- ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~0xf00000, LTQ_CGU_IFCCR);
- ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | 0x800000, LTQ_CGU_IFCCR);
+ if (ltq_is_ar9()) {
+ ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~0x1f00000, LTQ_CGU_IFCCR);
+ ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | 0xe00000, LTQ_CGU_IFCCR);
+ } else {
+ ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) & ~0xf00000, LTQ_CGU_IFCCR);
+ ltq_cgu_w32(ltq_cgu_r32(LTQ_CGU_IFCCR) | 0x800000, LTQ_CGU_IFCCR);
+ }
/* external or internal clock ? */
if (conf->clock) {

View File

@ -1,22 +0,0 @@
Index: linux-3.0.3/arch/mips/lantiq/clk.c
===================================================================
--- linux-3.0.3.orig/arch/mips/lantiq/clk.c 2011-09-29 20:43:07.000000000 +0200
+++ linux-3.0.3/arch/mips/lantiq/clk.c 2011-09-29 20:45:14.785132132 +0200
@@ -91,6 +91,17 @@
}
EXPORT_SYMBOL(clk_put);
+int clk_enable(struct clk *clk)
+{
+ /* clocks are always enabled*/
+ return 0;
+}
+
+void clk_disable(struct clk *clk)
+{
+ /* clocks are always enabled*/
+}
+
static inline u32 ltq_get_counter_resolution(void)
{
u32 res;

View File

@ -1,56 +0,0 @@
commit 1c388919d89ca35741e9c4d3255adf87f76f0c06
Author: Geert Uytterhoeven <geert@linux-m68k.org>
Date: Sat May 7 20:53:16 2011 +0200
resources: Add lookup_resource()
Add a function to find an existing resource by a resource start address.
This allows to implement simple allocators (with a malloc/free-alike API)
on top of the resource system.
Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org>
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index e9bb22c..63eb429 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -132,6 +132,7 @@ extern int allocate_resource(struct resource *root, struct resource *new,
resource_size_t,
resource_size_t),
void *alignf_data);
+struct resource *lookup_resource(struct resource *root, resource_size_t start);
int adjust_resource(struct resource *res, resource_size_t start,
resource_size_t size);
resource_size_t resource_alignment(struct resource *res);
diff --git a/kernel/resource.c b/kernel/resource.c
index 3ff4017..3b3cedc 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -553,6 +553,27 @@ int allocate_resource(struct resource *root, struct resource *new,
EXPORT_SYMBOL(allocate_resource);
+/**
+ * lookup_resource - find an existing resource by a resource start address
+ * @root: root resource descriptor
+ * @start: resource start address
+ *
+ * Returns a pointer to the resource if found, NULL otherwise
+ */
+struct resource *lookup_resource(struct resource *root, resource_size_t start)
+{
+ struct resource *res;
+
+ read_lock(&resource_lock);
+ for (res = root->child; res; res = res->sibling) {
+ if (res->start == start)
+ break;
+ }
+ read_unlock(&resource_lock);
+
+ return res;
+}
+
/*
* Insert a resource into the resource tree. If successful, return NULL,
* otherwise return the conflicting resource (compare to __request_resource())

View File

@ -15,8 +15,6 @@ Cc: linux-mips@linux-mips.org
arch/mips/lantiq/early_printk.c | 14 ++++++++------
2 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
index 8a3c6be..e6d1ca0 100644
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
@@ -34,6 +34,10 @@
@ -30,8 +28,6 @@ index 8a3c6be..e6d1ca0 100644
/* RCU - reset control unit */
#define LTQ_RCU_BASE_ADDR 0x1F203000
#define LTQ_RCU_SIZE 0x1000
diff --git a/arch/mips/lantiq/early_printk.c b/arch/mips/lantiq/early_printk.c
index 972e05f..5089075 100644
--- a/arch/mips/lantiq/early_printk.c
+++ b/arch/mips/lantiq/early_printk.c
@@ -12,11 +12,13 @@
@ -62,6 +58,3 @@ index 972e05f..5089075 100644
+ ltq_w8(c, LTQ_ASC_TBUF);
local_irq_restore(flags);
}
--
1.7.5.4

View File

@ -13,11 +13,9 @@ Cc: linux-mips@linux-mips.org
arch/mips/lantiq/prom.c | 6 ++++--
1 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c
index 56ba007..5035c10 100644
--- a/arch/mips/lantiq/prom.c
+++ b/arch/mips/lantiq/prom.c
@@ -45,10 +45,12 @@ static void __init prom_init_cmdline(void)
@@ -45,10 +45,12 @@ static void __init prom_init_cmdline(voi
char **argv = (char **) KSEG1ADDR(fw_arg1);
int i;
@ -32,6 +30,3 @@ index 56ba007..5035c10 100644
strlcat(arcs_cmdline, p, sizeof(arcs_cmdline));
strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline));
}
--
1.7.5.4

View File

@ -40,8 +40,6 @@ Cc: linux-mips@linux-mips.org
delete mode 100644 arch/mips/lantiq/xway/setup-xway.c
create mode 100644 arch/mips/lantiq/xway/sysctrl.c
diff --git a/arch/mips/include/asm/mach-lantiq/lantiq.h b/arch/mips/include/asm/mach-lantiq/lantiq.h
index ce2f029..66d7300 100644
--- a/arch/mips/include/asm/mach-lantiq/lantiq.h
+++ b/arch/mips/include/asm/mach-lantiq/lantiq.h
@@ -9,6 +9,7 @@
@ -68,7 +66,7 @@ index ce2f029..66d7300 100644
extern unsigned int ltq_get_cpu_ver(void);
extern unsigned int ltq_get_soc_type(void);
@@ -51,7 +43,9 @@ extern void ltq_enable_irq(struct irq_data *data);
@@ -51,7 +43,9 @@ extern void ltq_enable_irq(struct irq_da
/* find out what caused the last cpu reset */
extern int ltq_reset_cause(void);
@ -79,8 +77,6 @@ index ce2f029..66d7300 100644
#define IOPORT_RESOURCE_START 0x10000000
#define IOPORT_RESOURCE_END 0xffffffff
diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
index e6d1ca0..da8ff95 100644
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
@@ -65,6 +65,8 @@
@ -123,8 +119,6 @@ index e6d1ca0..da8ff95 100644
static inline int ltq_is_ar9(void)
{
diff --git a/arch/mips/lantiq/clk.c b/arch/mips/lantiq/clk.c
index 7e9c0ff..4254f08 100644
--- a/arch/mips/lantiq/clk.c
+++ b/arch/mips/lantiq/clk.c
@@ -22,6 +22,7 @@
@ -158,12 +152,12 @@ index 7e9c0ff..4254f08 100644
- if (insert_resource(&iomem_resource, &ltq_cgu_resource) < 0)
- panic("Failed to insert cgu memory\n");
-
+ ltq_soc_init();
- if (request_mem_region(ltq_cgu_resource.start,
- resource_size(&ltq_cgu_resource), "cgu") < 0)
- panic("Failed to request cgu memory\n");
+ ltq_soc_init();
-
- ltq_cgu_membase = ioremap_nocache(ltq_cgu_resource.start,
- resource_size(&ltq_cgu_resource));
- if (!ltq_cgu_membase) {
@ -176,8 +170,6 @@ index 7e9c0ff..4254f08 100644
+ pr_info("CPU Clock: %ldMHz\n", clk_get_rate(clk) / 1000000);
clk_put(clk);
}
diff --git a/arch/mips/lantiq/devices.c b/arch/mips/lantiq/devices.c
index 44a3677..81c7aab 100644
--- a/arch/mips/lantiq/devices.c
+++ b/arch/mips/lantiq/devices.c
@@ -27,12 +27,8 @@
@ -195,7 +187,7 @@ index 44a3677..81c7aab 100644
static struct platform_device ltq_nor = {
.name = "ltq_nor",
@@ -47,12 +43,8 @@ void __init ltq_register_nor(struct physmap_flash_data *data)
@@ -47,12 +43,8 @@ void __init ltq_register_nor(struct phys
}
/* watchdog */
@ -237,8 +229,6 @@ index 44a3677..81c7aab 100644
IRQ_RES(tx, LTQ_ASC_TIR(1)),
IRQ_RES(rx, LTQ_ASC_RIR(1)),
IRQ_RES(err, LTQ_ASC_EIR(1)),
diff --git a/arch/mips/lantiq/devices.h b/arch/mips/lantiq/devices.h
index 2947bb1..a03c23f 100644
--- a/arch/mips/lantiq/devices.h
+++ b/arch/mips/lantiq/devices.h
@@ -14,6 +14,10 @@
@ -252,8 +242,6 @@ index 2947bb1..a03c23f 100644
extern void ltq_register_nor(struct physmap_flash_data *data);
extern void ltq_register_wdt(void);
diff --git a/arch/mips/lantiq/prom.c b/arch/mips/lantiq/prom.c
index 5035c10..fead2cc 100644
--- a/arch/mips/lantiq/prom.c
+++ b/arch/mips/lantiq/prom.c
@@ -16,6 +16,10 @@
@ -267,7 +255,7 @@ index 5035c10..fead2cc 100644
static struct ltq_soc_info soc_info;
unsigned int ltq_get_cpu_ver(void)
@@ -57,16 +61,50 @@ static void __init prom_init_cmdline(void)
@@ -57,16 +61,50 @@ static void __init prom_init_cmdline(voi
}
}
@ -277,7 +265,7 @@ index 5035c10..fead2cc 100644
- struct clk *clk;
+ __iomem void *ret = NULL;
+ struct resource *lookup = lookup_resource(&iomem_resource, res->start);
+
+ if (lookup && strcmp(lookup->name, res->name)) {
+ panic("conflicting memory range %s\n", res->name);
+ return NULL;
@ -293,7 +281,7 @@ index 5035c10..fead2cc 100644
+ panic("Failed to request %s memory\n", res->name);
+ goto err_res;
+ }
+
+ ret = ioremap_nocache(res->start, resource_size(res));
+ if (!ret)
+ goto err_mem;
@ -324,8 +312,6 @@ index 5035c10..fead2cc 100644
soc_info.sys_type[LTQ_SYS_TYPE_LEN - 1] = '\0';
pr_info("SoC: %s\n", soc_info.sys_type);
prom_init_cmdline();
diff --git a/arch/mips/lantiq/prom.h b/arch/mips/lantiq/prom.h
index b4229d9..51dba1b 100644
--- a/arch/mips/lantiq/prom.h
+++ b/arch/mips/lantiq/prom.h
@@ -9,17 +9,21 @@
@ -350,8 +336,6 @@ index b4229d9..51dba1b 100644
extern void ltq_soc_setup(void);
#endif
diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
index c517f2e..6678402 100644
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -1,7 +1,7 @@
@ -365,8 +349,6 @@ index c517f2e..6678402 100644
obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o
obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o
diff --git a/arch/mips/lantiq/xway/devices.c b/arch/mips/lantiq/xway/devices.c
index d0e32ab..9bacaa8 100644
--- a/arch/mips/lantiq/xway/devices.c
+++ b/arch/mips/lantiq/xway/devices.c
@@ -31,22 +31,9 @@
@ -439,8 +421,6 @@ index d0e32ab..9bacaa8 100644
static struct platform_device ltq_etop = {
.name = "ltq_etop",
diff --git a/arch/mips/lantiq/xway/dma.c b/arch/mips/lantiq/xway/dma.c
index 4278a45..af35e62 100644
--- a/arch/mips/lantiq/xway/dma.c
+++ b/arch/mips/lantiq/xway/dma.c
@@ -23,6 +23,8 @@
@ -486,12 +466,9 @@ index 4278a45..af35e62 100644
if (!ltq_dma_membase)
panic("Failed to remap dma memory\n");
diff --git a/arch/mips/lantiq/xway/ebu.c b/arch/mips/lantiq/xway/ebu.c
deleted file mode 100644
index 66eb52f..0000000
--- a/arch/mips/lantiq/xway/ebu.c
+++ /dev/null
@@ -1,53 +0,0 @@
@@ -1,52 +0,0 @@
-/*
- * 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
@ -504,7 +481,6 @@ index 66eb52f..0000000
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/ioport.h>
-
-#include <lantiq_soc.h>
@ -545,12 +521,9 @@ index 66eb52f..0000000
-}
-
-postcore_initcall(lantiq_ebu_init);
diff --git a/arch/mips/lantiq/xway/pmu.c b/arch/mips/lantiq/xway/pmu.c
deleted file mode 100644
index 9d69f01e..0000000
--- a/arch/mips/lantiq/xway/pmu.c
+++ /dev/null
@@ -1,70 +0,0 @@
@@ -1,69 +0,0 @@
-/*
- * 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
@ -561,7 +534,6 @@ index 9d69f01e..0000000
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/version.h>
-#include <linux/ioport.h>
-
-#include <lantiq_soc.h>
@ -621,8 +593,6 @@ index 9d69f01e..0000000
-}
-
-core_initcall(ltq_pmu_init);
diff --git a/arch/mips/lantiq/xway/prom-ase.c b/arch/mips/lantiq/xway/prom-ase.c
index abe49f4..aaccdcb 100644
--- a/arch/mips/lantiq/xway/prom-ase.c
+++ b/arch/mips/lantiq/xway/prom-ase.c
@@ -13,6 +13,7 @@
@ -633,7 +603,7 @@ index abe49f4..aaccdcb 100644
#include "../prom.h"
#define SOC_AMAZON_SE "Amazon_SE"
@@ -26,6 +27,7 @@ void __init ltq_soc_detect(struct ltq_soc_info *i)
@@ -26,6 +27,7 @@ void __init ltq_soc_detect(struct ltq_so
{
i->partnum = (ltq_r32(LTQ_MPS_CHIPID) & PART_MASK) >> PART_SHIFT;
i->rev = (ltq_r32(LTQ_MPS_CHIPID) & REV_MASK) >> REV_SHIFT;
@ -641,7 +611,7 @@ index abe49f4..aaccdcb 100644
switch (i->partnum) {
case SOC_ID_AMAZON_SE:
i->name = SOC_AMAZON_SE;
@@ -37,3 +39,10 @@ void __init ltq_soc_detect(struct ltq_soc_info *i)
@@ -37,3 +39,10 @@ void __init ltq_soc_detect(struct ltq_so
break;
}
}
@ -652,8 +622,6 @@ index abe49f4..aaccdcb 100644
+ ltq_register_gpio();
+ ltq_register_wdt();
+}
diff --git a/arch/mips/lantiq/xway/prom-xway.c b/arch/mips/lantiq/xway/prom-xway.c
index 1686692a..f3d1228 100644
--- a/arch/mips/lantiq/xway/prom-xway.c
+++ b/arch/mips/lantiq/xway/prom-xway.c
@@ -13,6 +13,7 @@
@ -664,7 +632,7 @@ index 1686692a..f3d1228 100644
#include "../prom.h"
#define SOC_DANUBE "Danube"
@@ -28,6 +29,7 @@ void __init ltq_soc_detect(struct ltq_soc_info *i)
@@ -28,6 +29,7 @@ void __init ltq_soc_detect(struct ltq_so
{
i->partnum = (ltq_r32(LTQ_MPS_CHIPID) & PART_MASK) >> PART_SHIFT;
i->rev = (ltq_r32(LTQ_MPS_CHIPID) & REV_MASK) >> REV_SHIFT;
@ -672,7 +640,7 @@ index 1686692a..f3d1228 100644
switch (i->partnum) {
case SOC_ID_DANUBE1:
case SOC_ID_DANUBE2:
@@ -52,3 +54,11 @@ void __init ltq_soc_detect(struct ltq_soc_info *i)
@@ -52,3 +54,11 @@ void __init ltq_soc_detect(struct ltq_so
break;
}
}
@ -684,8 +652,6 @@ index 1686692a..f3d1228 100644
+ ltq_register_gpio();
+ ltq_register_wdt();
+}
diff --git a/arch/mips/lantiq/xway/reset.c b/arch/mips/lantiq/xway/reset.c
index a1be36d..e701a48 100644
--- a/arch/mips/lantiq/xway/reset.c
+++ b/arch/mips/lantiq/xway/reset.c
@@ -15,6 +15,8 @@
@ -731,9 +697,6 @@ index a1be36d..e701a48 100644
if (!ltq_rcu_membase)
panic("Failed to remap rcu memory\n");
diff --git a/arch/mips/lantiq/xway/setup-ase.c b/arch/mips/lantiq/xway/setup-ase.c
deleted file mode 100644
index f6f3267..0000000
--- a/arch/mips/lantiq/xway/setup-ase.c
+++ /dev/null
@@ -1,19 +0,0 @@
@ -756,9 +719,6 @@ index f6f3267..0000000
- ltq_register_gpio();
- ltq_register_wdt();
-}
diff --git a/arch/mips/lantiq/xway/setup-xway.c b/arch/mips/lantiq/xway/setup-xway.c
deleted file mode 100644
index c292f64..0000000
--- a/arch/mips/lantiq/xway/setup-xway.c
+++ /dev/null
@@ -1,20 +0,0 @@
@ -782,9 +742,6 @@ index c292f64..0000000
- ltq_register_gpio();
- ltq_register_wdt();
-}
diff --git a/arch/mips/lantiq/xway/sysctrl.c b/arch/mips/lantiq/xway/sysctrl.c
new file mode 100644
index 0000000..a29944f
--- /dev/null
+++ b/arch/mips/lantiq/xway/sysctrl.c
@@ -0,0 +1,77 @@
@ -865,8 +822,6 @@ index 0000000..a29944f
+ /* make sure to unprotect the memory region where flash is located */
+ ltq_ebu_w32(ltq_ebu_r32(LTQ_EBU_BUSCON0) & ~EBU_WRDIS, LTQ_EBU_BUSCON0);
+}
diff --git a/drivers/watchdog/lantiq_wdt.c b/drivers/watchdog/lantiq_wdt.c
index 102aed0..179bf98 100644
--- a/drivers/watchdog/lantiq_wdt.c
+++ b/drivers/watchdog/lantiq_wdt.c
@@ -16,7 +16,7 @@
@ -878,6 +833,3 @@ index 102aed0..179bf98 100644
/* Section 3.4 of the datasheet
* The password sequence protects the WDT control register from unintended
--
1.7.5.4

View File

@ -17,11 +17,9 @@ Cc: linux-mips@linux-mips.org
arch/mips/lantiq/irq.c | 24 +++++++++++++-----------
1 files changed, 13 insertions(+), 11 deletions(-)
diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
index f9737bb..17c057f 100644
--- a/arch/mips/lantiq/irq.c
+++ b/arch/mips/lantiq/irq.c
@@ -195,7 +195,7 @@ static void ltq_hw_irqdispatch(int module)
@@ -195,7 +195,7 @@ static void ltq_hw_irqdispatch(int modul
do_IRQ((int)irq + INT_NUM_IM0_IRL0 + (INT_NUM_IM_OFFSET * module));
/* if this is a EBU irq, we need to ack it or get a deadlock */
@ -39,14 +37,15 @@ index f9737bb..17c057f 100644
+ if (LTQ_EIU_BASE_ADDR) {
+ if (insert_resource(&iomem_resource, &ltq_eiu_resource) < 0)
+ panic("Failed to insert eiu memory\n");
- if (request_mem_region(ltq_eiu_resource.start,
- resource_size(&ltq_eiu_resource), "eiu") < 0)
- panic("Failed to request eiu memory\n");
+
+ if (request_mem_region(ltq_eiu_resource.start,
+ resource_size(&ltq_eiu_resource), "eiu") < 0)
+ panic("Failed to request eiu memory\n");
- if (request_mem_region(ltq_eiu_resource.start,
- resource_size(&ltq_eiu_resource), "eiu") < 0)
- panic("Failed to request eiu memory\n");
-
- ltq_eiu_membase = ioremap_nocache(ltq_eiu_resource.start,
+ ltq_eiu_membase = ioremap_nocache(ltq_eiu_resource.start,
resource_size(&ltq_eiu_resource));
@ -69,6 +68,3 @@ index f9737bb..17c057f 100644
irq_set_chip_and_handler(i, &ltq_eiu_type,
handle_level_irq);
/* EIU3-5 only exist on ar9 and vr9 */
--
1.7.5.4

View File

@ -36,9 +36,6 @@ Cc: linux-mips@linux-mips.org
create mode 100644 arch/mips/lantiq/falcon/reset.c
create mode 100644 arch/mips/lantiq/falcon/sysctrl.c
diff --git a/arch/mips/include/asm/mach-lantiq/falcon/falcon_irq.h b/arch/mips/include/asm/mach-lantiq/falcon/falcon_irq.h
new file mode 100644
index 0000000..4dc6466
--- /dev/null
+++ b/arch/mips/include/asm/mach-lantiq/falcon/falcon_irq.h
@@ -0,0 +1,268 @@
@ -310,9 +307,6 @@ index 0000000..4dc6466
+#define FALCON_IRQ_VPE0_PMCIR (INT_NUM_IM4_IRL0 + 31)
+
+#endif /* _FALCON_IRQ__ */
diff --git a/arch/mips/include/asm/mach-lantiq/falcon/irq.h b/arch/mips/include/asm/mach-lantiq/falcon/irq.h
new file mode 100644
index 0000000..2caccd9
--- /dev/null
+++ b/arch/mips/include/asm/mach-lantiq/falcon/irq.h
@@ -0,0 +1,18 @@
@ -334,9 +328,6 @@ index 0000000..2caccd9
+#include_next <irq.h>
+
+#endif
diff --git a/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
new file mode 100644
index 0000000..c092531
--- /dev/null
+++ b/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
@@ -0,0 +1,140 @@
@ -480,11 +471,9 @@ index 0000000..c092531
+
+#endif /* CONFIG_SOC_FALCON */
+#endif /* _LTQ_XWAY_H__ */
diff --git a/arch/mips/include/asm/mach-lantiq/lantiq.h b/arch/mips/include/asm/mach-lantiq/lantiq.h
index 66d7300..188de0f 100644
--- a/arch/mips/include/asm/mach-lantiq/lantiq.h
+++ b/arch/mips/include/asm/mach-lantiq/lantiq.h
@@ -25,6 +25,7 @@ extern unsigned int ltq_get_soc_type(void);
@@ -25,6 +25,7 @@ extern unsigned int ltq_get_soc_type(voi
/* clock speeds */
#define CLOCK_60M 60000000
#define CLOCK_83M 83333333
@ -492,8 +481,6 @@ index 66d7300..188de0f 100644
#define CLOCK_111M 111111111
#define CLOCK_133M 133333333
#define CLOCK_167M 166666667
diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig
index 3fccf21..cb6b39f 100644
--- a/arch/mips/lantiq/Kconfig
+++ b/arch/mips/lantiq/Kconfig
@@ -16,8 +16,12 @@ config SOC_XWAY
@ -509,17 +496,13 @@ index 3fccf21..cb6b39f 100644
+source "arch/mips/lantiq/falcon/Kconfig"
endif
diff --git a/arch/mips/lantiq/Makefile b/arch/mips/lantiq/Makefile
index e5dae0e..7e9c69e 100644
--- a/arch/mips/lantiq/Makefile
+++ b/arch/mips/lantiq/Makefile
@@ -9,3 +9,4 @@ obj-y := irq.o setup.o clk.o prom.o devices.o
@@ -9,3 +9,4 @@ obj-y := irq.o setup.o clk.o prom.o devi
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_SOC_TYPE_XWAY) += xway/
+obj-$(CONFIG_SOC_FALCON) += falcon/
diff --git a/arch/mips/lantiq/Platform b/arch/mips/lantiq/Platform
index f3dff05..b3ec498 100644
--- a/arch/mips/lantiq/Platform
+++ b/arch/mips/lantiq/Platform
@@ -6,3 +6,4 @@ platform-$(CONFIG_LANTIQ) += lantiq/
@ -527,16 +510,10 @@ index f3dff05..b3ec498 100644
load-$(CONFIG_LANTIQ) = 0xffffffff80002000
cflags-$(CONFIG_SOC_TYPE_XWAY) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/xway
+cflags-$(CONFIG_SOC_FALCON) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/falcon
diff --git a/arch/mips/lantiq/falcon/Makefile b/arch/mips/lantiq/falcon/Makefile
new file mode 100644
index 0000000..e9c7455
--- /dev/null
+++ b/arch/mips/lantiq/falcon/Makefile
@@ -0,0 +1 @@
+obj-y := clk.o prom.o reset.o sysctrl.o devices.o
diff --git a/arch/mips/lantiq/falcon/clk.c b/arch/mips/lantiq/falcon/clk.c
new file mode 100644
index 0000000..1a550ea
--- /dev/null
+++ b/arch/mips/lantiq/falcon/clk.c
@@ -0,0 +1,44 @@
@ -584,9 +561,6 @@ index 0000000..1a550ea
+ return CLOCK_100M;
+}
+EXPORT_SYMBOL(ltq_get_fpi_hz);
diff --git a/arch/mips/lantiq/falcon/devices.c b/arch/mips/lantiq/falcon/devices.c
new file mode 100644
index 0000000..c4606f2
--- /dev/null
+++ b/arch/mips/lantiq/falcon/devices.c
@@ -0,0 +1,87 @@
@ -677,9 +651,6 @@ index 0000000..c4606f2
+{
+ platform_device_register(&ltq_flash_nand);
+}
diff --git a/arch/mips/lantiq/falcon/devices.h b/arch/mips/lantiq/falcon/devices.h
new file mode 100644
index 0000000..e802a7c
--- /dev/null
+++ b/arch/mips/lantiq/falcon/devices.h
@@ -0,0 +1,18 @@
@ -701,9 +672,6 @@ index 0000000..e802a7c
+extern void falcon_register_nand(void);
+
+#endif
diff --git a/arch/mips/lantiq/falcon/prom.c b/arch/mips/lantiq/falcon/prom.c
new file mode 100644
index 0000000..89367c4
--- /dev/null
+++ b/arch/mips/lantiq/falcon/prom.c
@@ -0,0 +1,72 @@
@ -779,9 +747,6 @@ index 0000000..89367c4
+ break;
+ }
+}
diff --git a/arch/mips/lantiq/falcon/reset.c b/arch/mips/lantiq/falcon/reset.c
new file mode 100644
index 0000000..d3289ca
--- /dev/null
+++ b/arch/mips/lantiq/falcon/reset.c
@@ -0,0 +1,87 @@
@ -872,9 +837,6 @@ index 0000000..d3289ca
+}
+
+arch_initcall(mips_reboot_setup);
diff --git a/arch/mips/lantiq/falcon/sysctrl.c b/arch/mips/lantiq/falcon/sysctrl.c
new file mode 100644
index 0000000..d20b46b
--- /dev/null
+++ b/arch/mips/lantiq/falcon/sysctrl.c
@@ -0,0 +1,181 @@
@ -1059,6 +1021,3 @@ index 0000000..d20b46b
+
+ ltq_gpe_enable();
+}
--
1.7.5.4

View File

@ -17,15 +17,11 @@ Cc: linux-mips@linux-mips.org
4 files changed, 442 insertions(+), 1 deletions(-)
create mode 100644 arch/mips/lantiq/falcon/gpio.c
diff --git a/arch/mips/lantiq/falcon/Makefile b/arch/mips/lantiq/falcon/Makefile
index e9c7455..de72209 100644
--- a/arch/mips/lantiq/falcon/Makefile
+++ b/arch/mips/lantiq/falcon/Makefile
@@ -1 +1 @@
-obj-y := clk.o prom.o reset.o sysctrl.o devices.o
+obj-y := clk.o prom.o reset.o sysctrl.o devices.o gpio.o
diff --git a/arch/mips/lantiq/falcon/devices.c b/arch/mips/lantiq/falcon/devices.c
index c4606f2..4f47b44 100644
--- a/arch/mips/lantiq/falcon/devices.c
+++ b/arch/mips/lantiq/falcon/devices.c
@@ -9,6 +9,7 @@
@ -80,8 +76,6 @@ index c4606f2..4f47b44 100644
+ ltq_sysctl_activate(SYSCTL_SYS1,
+ ACTS_PADCTRL3 | ACTS_PADCTRL4 | ACTS_P3 | ACTS_P4);
+}
diff --git a/arch/mips/lantiq/falcon/devices.h b/arch/mips/lantiq/falcon/devices.h
index e802a7c..18be8b6 100644
--- a/arch/mips/lantiq/falcon/devices.h
+++ b/arch/mips/lantiq/falcon/devices.h
@@ -14,5 +14,7 @@
@ -92,9 +86,6 @@ index e802a7c..18be8b6 100644
+extern void falcon_register_gpio_extra(void);
#endif
diff --git a/arch/mips/lantiq/falcon/gpio.c b/arch/mips/lantiq/falcon/gpio.c
new file mode 100644
index 0000000..b87582d
--- /dev/null
+++ b/arch/mips/lantiq/falcon/gpio.c
@@ -0,0 +1,398 @@
@ -496,6 +487,3 @@ index 0000000..b87582d
+}
+
+postcore_initcall(falcon_gpio_init);
--
1.7.5.4

View File

@ -18,9 +18,6 @@ Cc: linux-mips@linux-mips.org
create mode 100644 arch/mips/lantiq/falcon/Kconfig
create mode 100644 arch/mips/lantiq/falcon/mach-easy98000.c
diff --git a/arch/mips/lantiq/falcon/Kconfig b/arch/mips/lantiq/falcon/Kconfig
new file mode 100644
index 0000000..03e999d
--- /dev/null
+++ b/arch/mips/lantiq/falcon/Kconfig
@@ -0,0 +1,11 @@
@ -35,16 +32,11 @@ index 0000000..03e999d
+endmenu
+
+endif
diff --git a/arch/mips/lantiq/falcon/Makefile b/arch/mips/lantiq/falcon/Makefile
index de72209..56b22eb 100644
--- a/arch/mips/lantiq/falcon/Makefile
+++ b/arch/mips/lantiq/falcon/Makefile
@@ -1 +1,2 @@
obj-y := clk.o prom.o reset.o sysctrl.o devices.o gpio.o
+obj-$(CONFIG_LANTIQ_MACH_EASY98000) += mach-easy98000.o
diff --git a/arch/mips/lantiq/falcon/mach-easy98000.c b/arch/mips/lantiq/falcon/mach-easy98000.c
new file mode 100644
index 0000000..361b8f0
--- /dev/null
+++ b/arch/mips/lantiq/falcon/mach-easy98000.c
@@ -0,0 +1,110 @@
@ -158,8 +150,6 @@ index 0000000..361b8f0
+ "EASY98000NAND",
+ "EASY98000 Eval Board (NAND Flash)",
+ easy98000nand_init);
diff --git a/arch/mips/lantiq/machtypes.h b/arch/mips/lantiq/machtypes.h
index 7e01b8c..dfc6af7 100644
--- a/arch/mips/lantiq/machtypes.h
+++ b/arch/mips/lantiq/machtypes.h
@@ -15,6 +15,11 @@ enum lantiq_mach_type {
@ -174,6 +164,3 @@ index 7e01b8c..dfc6af7 100644
};
#endif
--
1.7.5.4

View File

@ -14,12 +14,10 @@ Cc: linux-mips@linux-mips.org
arch/mips/oprofile/op_model_mipsxx.c | 12 ++++++++++++
1 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/arch/mips/oprofile/op_model_mipsxx.c b/arch/mips/oprofile/op_model_mipsxx.c
index 54759f1..86cf234 100644
--- a/arch/mips/oprofile/op_model_mipsxx.c
+++ b/arch/mips/oprofile/op_model_mipsxx.c
@@ -298,6 +298,11 @@ static void reset_counters(void *arg)
}
@@ -303,6 +303,11 @@ static irqreturn_t mipsxx_perfcount_int(
return mipsxx_perfcount_handler();
}
+static irqreturn_t mipsxx_perfcount_int(int irq, void *dev_id)
@ -30,9 +28,9 @@ index 54759f1..86cf234 100644
static int __init mipsxx_init(void)
{
int counters;
@@ -374,6 +379,10 @@ static int __init mipsxx_init(void)
save_perf_irq = perf_irq;
perf_irq = mipsxx_perfcount_handler;
@@ -383,6 +388,10 @@ static int __init mipsxx_init(void)
return request_irq(cp0_perfcount_irq, mipsxx_perfcount_int,
IRQF_SHARED, "Perfcounter", save_perf_irq);
+ if (cp0_perfcount_irq >= 0)
+ return request_irq(cp0_perfcount_irq, mipsxx_perfcount_int,
@ -41,16 +39,13 @@ index 54759f1..86cf234 100644
return 0;
}
@@ -381,6 +390,9 @@ static void mipsxx_exit(void)
{
int counters = op_model_mipsxx_ops.num_counters;
@@ -392,6 +401,9 @@ static void mipsxx_exit(void)
if (cp0_perfcount_irq >= 0)
free_irq(cp0_perfcount_irq, save_perf_irq);
+
+ if (cp0_perfcount_irq >= 0)
+ free_irq(cp0_perfcount_irq, save_perf_irq);
+
counters = counters_per_cpu_to_total(counters);
on_each_cpu(reset_counters, (void *)(long)counters, 1);
--
1.7.5.4

View File

@ -12,8 +12,6 @@ Cc: linux-mips@linux-mips.org
arch/mips/lantiq/irq.c | 5 +++++
2 files changed, 6 insertions(+), 0 deletions(-)
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index b122adc..0cf5bbd 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -230,6 +230,7 @@ config LANTIQ
@ -24,8 +22,6 @@ index b122adc..0cf5bbd 100644
select MIPS_MACHINE
config LASAT
diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
index 17c057f..0b2ed87 100644
--- a/arch/mips/lantiq/irq.c
+++ b/arch/mips/lantiq/irq.c
@@ -40,6 +40,9 @@
@ -47,6 +43,3 @@ index 17c057f..0b2ed87 100644
}
unsigned int __cpuinit get_c0_compare_int(void)
--
1.7.5.4

View File

@ -12,8 +12,6 @@ Subject: [PATCH 11/24] MIPS: lantiq: adds falcon I2C
5 files changed, 842 insertions(+), 0 deletions(-)
create mode 100644 drivers/i2c/busses/i2c-falcon.c
diff --git a/arch/mips/lantiq/falcon/devices.c b/arch/mips/lantiq/falcon/devices.c
index 4f47b44..a998b6b 100644
--- a/arch/mips/lantiq/falcon/devices.c
+++ b/arch/mips/lantiq/falcon/devices.c
@@ -126,3 +126,24 @@ falcon_register_gpio_extra(void)
@ -41,8 +39,6 @@ index 4f47b44..a998b6b 100644
+{
+ platform_device_register_simple("ltq_falcon_deu", 0, NULL, 0);
+}
diff --git a/arch/mips/lantiq/falcon/devices.h b/arch/mips/lantiq/falcon/devices.h
index 18be8b6..2fdcb08 100644
--- a/arch/mips/lantiq/falcon/devices.h
+++ b/arch/mips/lantiq/falcon/devices.h
@@ -16,5 +16,6 @@
@ -52,8 +48,6 @@ index 18be8b6..2fdcb08 100644
+extern void falcon_register_i2c(void);
#endif
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 646068e..e6c3ab6 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -284,6 +284,10 @@ config I2C_POWERMAC
@ -67,8 +61,6 @@ index 646068e..e6c3ab6 100644
config I2C_AT91
tristate "Atmel AT91 I2C Two-Wire interface (TWI)"
depends on ARCH_AT91 && EXPERIMENTAL && BROKEN
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index e6cf294..83e9250 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -82,5 +82,6 @@ obj-$(CONFIG_I2C_SIBYTE) += i2c-sibyte.o
@ -78,9 +70,6 @@ index e6cf294..83e9250 100644
+obj-$(CONFIG_I2C_FALCON) += i2c-falcon.o
ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG
diff --git a/drivers/i2c/busses/i2c-falcon.c b/drivers/i2c/busses/i2c-falcon.c
new file mode 100644
index 0000000..7bb1253
--- /dev/null
+++ b/drivers/i2c/busses/i2c-falcon.c
@@ -0,0 +1,815 @@
@ -899,6 +888,3 @@ index 0000000..7bb1253
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_VERSION);
--
1.7.5.4

View File

@ -18,11 +18,9 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
6 files changed, 523 insertions(+), 2 deletions(-)
create mode 100644 drivers/spi/spi-falcon.c
Index: linux-3.0.3/arch/mips/lantiq/falcon/devices.c
===================================================================
--- linux-3.0.3.orig/arch/mips/lantiq/falcon/devices.c 2011-10-05 12:30:34.584838403 +0200
+++ linux-3.0.3/arch/mips/lantiq/falcon/devices.c 2011-10-05 12:42:58.696870214 +0200
@@ -129,7 +129,7 @@
--- a/arch/mips/lantiq/falcon/devices.c
+++ b/arch/mips/lantiq/falcon/devices.c
@@ -129,7 +129,7 @@ falcon_register_gpio_extra(void)
/* i2c */
static struct resource falcon_i2c_resources[] = {
@ -31,7 +29,7 @@ Index: linux-3.0.3/arch/mips/lantiq/falcon/devices.c
IRQ_RES("i2c_lb", FALCON_IRQ_I2C_LBREQ),
IRQ_RES("i2c_b", FALCON_IRQ_I2C_BREQ),
IRQ_RES("i2c_err", FALCON_IRQ_I2C_I2C_ERR),
@@ -140,10 +140,18 @@
@@ -140,10 +140,18 @@ void __init falcon_register_i2c(void)
{
platform_device_register_simple("i2c-falcon", 0,
falcon_i2c_resources, ARRAY_SIZE(falcon_i2c_resources));
@ -53,10 +51,8 @@ Index: linux-3.0.3/arch/mips/lantiq/falcon/devices.c
+ spi_register_board_info(data, 1);
+ platform_device_register(&ltq_spi);
}
Index: linux-3.0.3/arch/mips/lantiq/falcon/devices.h
===================================================================
--- linux-3.0.3.orig/arch/mips/lantiq/falcon/devices.h 2011-10-05 12:30:34.584838403 +0200
+++ linux-3.0.3/arch/mips/lantiq/falcon/devices.h 2011-10-05 12:30:34.600838405 +0200
--- a/arch/mips/lantiq/falcon/devices.h
+++ b/arch/mips/lantiq/falcon/devices.h
@@ -11,11 +11,15 @@
#ifndef _FALCON_DEVICES_H__
#define _FALCON_DEVICES_H__
@ -73,11 +69,9 @@ Index: linux-3.0.3/arch/mips/lantiq/falcon/devices.h
+extern void falcon_register_spi_flash(struct spi_board_info *data);
#endif
Index: linux-3.0.3/arch/mips/lantiq/falcon/mach-easy98000.c
===================================================================
--- linux-3.0.3.orig/arch/mips/lantiq/falcon/mach-easy98000.c 2011-10-05 12:30:34.552838402 +0200
+++ linux-3.0.3/arch/mips/lantiq/falcon/mach-easy98000.c 2011-10-05 12:30:34.600838405 +0200
@@ -40,6 +40,21 @@
--- a/arch/mips/lantiq/falcon/mach-easy98000.c
+++ b/arch/mips/lantiq/falcon/mach-easy98000.c
@@ -40,6 +40,21 @@ struct physmap_flash_data easy98000_nor_
.parts = easy98000_nor_partitions,
};
@ -99,7 +93,7 @@ Index: linux-3.0.3/arch/mips/lantiq/falcon/mach-easy98000.c
/* setup gpio based spi bus/device for access to the eeprom on the board */
#define SPI_GPIO_MRST 102
#define SPI_GPIO_MTSR 103
@@ -93,6 +108,13 @@
@@ -93,6 +108,13 @@ easy98000_init(void)
}
static void __init
@ -113,7 +107,7 @@ Index: linux-3.0.3/arch/mips/lantiq/falcon/mach-easy98000.c
easy98000nand_init(void)
{
easy98000_init_common();
@@ -104,6 +126,11 @@
@@ -104,6 +126,11 @@ MIPS_MACHINE(LANTIQ_MACH_EASY98000,
"EASY98000 Eval Board",
easy98000_init);
@ -125,11 +119,9 @@ Index: linux-3.0.3/arch/mips/lantiq/falcon/mach-easy98000.c
MIPS_MACHINE(LANTIQ_MACH_EASY98000NAND,
"EASY98000NAND",
"EASY98000 Eval Board (NAND Flash)",
Index: linux-3.0.3/drivers/spi/Kconfig
===================================================================
--- linux-3.0.3.orig/drivers/spi/Kconfig 2011-10-05 12:30:33.608838362 +0200
+++ linux-3.0.3/drivers/spi/Kconfig 2011-10-05 12:41:56.864867570 +0200
@@ -219,6 +219,10 @@
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -189,6 +189,10 @@ config SPI_MPC52xx
This drivers supports the MPC52xx SPI controller in master SPI
mode.
@ -140,22 +132,18 @@ Index: linux-3.0.3/drivers/spi/Kconfig
config SPI_MPC52xx_PSC
tristate "Freescale MPC52xx PSC SPI controller"
depends on PPC_MPC52xx && EXPERIMENTAL
Index: linux-3.0.3/drivers/spi/Makefile
===================================================================
--- linux-3.0.3.orig/drivers/spi/Makefile 2011-10-05 12:30:33.608838362 +0200
+++ linux-3.0.3/drivers/spi/Makefile 2011-10-05 12:41:56.884867571 +0200
@@ -56,6 +56,7 @@
obj-$(CONFIG_SPI_SH_MSIOF) += spi_sh_msiof.o
obj-$(CONFIG_SPI_STMP3XXX) += spi_stmp.o
obj-$(CONFIG_SPI_NUC900) += spi_nuc900.o
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -25,6 +25,7 @@ obj-$(CONFIG_SPI_DW_MMIO) += spi-dw-mmi
obj-$(CONFIG_SPI_DW_PCI) += spi-dw-midpci.o
spi-dw-midpci-objs := spi-dw-pci.o spi-dw-mid.o
obj-$(CONFIG_SPI_EP93XX) += spi-ep93xx.o
+obj-$(CONFIG_SPI_FALCON) += spi-falcon.o
# special build for s3c24xx spi driver with fiq support
spi_s3c24xx_hw-y := spi_s3c24xx.o
Index: linux-3.0.3/drivers/spi/spi-falcon.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-3.0.3/drivers/spi/spi-falcon.c 2011-10-05 12:30:34.600838405 +0200
obj-$(CONFIG_SPI_FSL_LIB) += spi-fsl-lib.o
obj-$(CONFIG_SPI_FSL_ESPI) += spi-fsl-espi.o
obj-$(CONFIG_SPI_FSL_SPI) += spi-fsl-spi.o
--- /dev/null
+++ b/drivers/spi/spi-falcon.c
@@ -0,0 +1,477 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
@ -634,10 +622,8 @@ Index: linux-3.0.3/drivers/spi/spi-falcon.c
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Lantiq Falcon SPI controller driver");
Index: linux-3.0.3/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
===================================================================
--- linux-3.0.3.orig/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h 2011-10-05 12:38:16.176858136 +0200
+++ linux-3.0.3/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h 2011-10-05 12:39:54.936862358 +0200
--- a/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/falcon/lantiq_soc.h
@@ -48,6 +48,10 @@
#define LTQ_EBU_MODCON 0x000C

View File

@ -13,11 +13,9 @@ Subject: [PATCH 14/24] MIPS: lantiq: adds xway spi
6 files changed, 1083 insertions(+), 1 deletions(-)
create mode 100644 drivers/spi/spi-xway.c
Index: linux-3.0.3/arch/mips/include/asm/mach-lantiq/lantiq_platform.h
===================================================================
--- linux-3.0.3.orig/arch/mips/include/asm/mach-lantiq/lantiq_platform.h 2011-08-17 19:57:16.000000000 +0200
+++ linux-3.0.3/arch/mips/include/asm/mach-lantiq/lantiq_platform.h 2011-10-04 20:05:23.962311503 +0200
@@ -50,4 +50,13 @@
--- a/arch/mips/include/asm/mach-lantiq/lantiq_platform.h
+++ b/arch/mips/include/asm/mach-lantiq/lantiq_platform.h
@@ -50,4 +50,13 @@ struct ltq_eth_data {
int mii_mode;
};
@ -31,10 +29,8 @@ Index: linux-3.0.3/arch/mips/include/asm/mach-lantiq/lantiq_platform.h
+};
+
#endif
Index: linux-3.0.3/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
===================================================================
--- linux-3.0.3.orig/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h 2011-08-17 19:57:16.000000000 +0200
+++ linux-3.0.3/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h 2011-10-04 20:05:23.962311503 +0200
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
@@ -27,6 +27,8 @@
#define LTQ_SSC_TIR (INT_NUM_IM0_IRL0 + 15)
@ -44,10 +40,8 @@ Index: linux-3.0.3/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
#define LTQ_SSC_EIR (INT_NUM_IM0_IRL0 + 16)
#define LTQ_MEI_DYING_GASP_INT (INT_NUM_IM1_IRL0 + 21)
Index: linux-3.0.3/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
===================================================================
--- linux-3.0.3.orig/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h 2011-10-04 20:03:54.934307699 +0200
+++ linux-3.0.3/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h 2011-10-04 20:05:23.966311504 +0200
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
@@ -81,6 +81,7 @@
#define PMU_DMA 0x0020
@ -56,11 +50,9 @@ Index: linux-3.0.3/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
#define PMU_LED 0x0800
#define PMU_GPT 0x1000
#define PMU_PPE 0x2000
Index: linux-3.0.3/drivers/spi/Kconfig
===================================================================
--- linux-3.0.3.orig/drivers/spi/Kconfig 2011-10-04 20:05:07.030310779 +0200
+++ linux-3.0.3/drivers/spi/Kconfig 2011-10-04 20:05:23.966311504 +0200
@@ -433,6 +433,14 @@
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -393,6 +393,14 @@ config SPI_NUC900
help
SPI driver for Nuvoton NUC900 series ARM SoCs
@ -75,22 +67,16 @@ Index: linux-3.0.3/drivers/spi/Kconfig
#
# Add new SPI master controllers in alphabetical order above this line
#
Index: linux-3.0.3/drivers/spi/Makefile
===================================================================
--- linux-3.0.3.orig/drivers/spi/Makefile 2011-10-04 20:05:20.000000000 +0200
+++ linux-3.0.3/drivers/spi/Makefile 2011-10-04 20:05:35.802312011 +0200
@@ -57,6 +57,7 @@
obj-$(CONFIG_SPI_STMP3XXX) += spi_stmp.o
obj-$(CONFIG_SPI_NUC900) += spi_nuc900.o
obj-$(CONFIG_SPI_FALCON) += spi-falcon.o
--- a/drivers/spi/Makefile
+++ b/drivers/spi/Makefile
@@ -60,4 +60,5 @@ obj-$(CONFIG_SPI_TLE62X0) += spi-tle62x
obj-$(CONFIG_SPI_TOPCLIFF_PCH) += spi-topcliff-pch.o
obj-$(CONFIG_SPI_TXX9) += spi-txx9.o
obj-$(CONFIG_SPI_XILINX) += spi-xilinx.o
+obj-$(CONFIG_SPI_XWAY) += spi-xway.o
# special build for s3c24xx spi driver with fiq support
spi_s3c24xx_hw-y := spi_s3c24xx.o
Index: linux-3.0.3/drivers/spi/spi-xway.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-3.0.3/drivers/spi/spi-xway.c 2011-10-04 20:05:23.966311504 +0200
--- /dev/null
+++ b/drivers/spi/spi-xway.c
@@ -0,0 +1,1062 @@
+/*
+ * Lantiq SoC SPI controller

View File

@ -17,10 +17,8 @@ Signed-off-by: Thomas Langer <thomas.langer@lantiq.com>
drivers/net/lantiq_etop.c | 172 ++++++++++++++++++--
5 files changed, 180 insertions(+), 40 deletions(-)
Index: linux-3.0.3/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
===================================================================
--- linux-3.0.3.orig/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h 2011-10-04 20:05:23.000000000 +0200
+++ linux-3.0.3/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h 2011-10-04 20:05:44.146312365 +0200
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
@@ -40,26 +40,8 @@
#define MIPS_CPU_TIMER_IRQ 7
@ -50,10 +48,8 @@ Index: linux-3.0.3/arch/mips/include/asm/mach-lantiq/xway/lantiq_irq.h
#define LTQ_PPE_MBOX_INT (INT_NUM_IM2_IRL0 + 24)
Index: linux-3.0.3/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
===================================================================
--- linux-3.0.3.orig/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h 2011-10-04 20:05:23.000000000 +0200
+++ linux-3.0.3/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h 2011-10-04 20:05:44.146312365 +0200
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
@@ -80,6 +80,7 @@
#define LTQ_PMU_SIZE 0x1000
@ -73,7 +69,7 @@ Index: linux-3.0.3/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
/* DMA */
#define LTQ_DMA_BASE_ADDR 0x1E104100
#define LTQ_DMA_SIZE 0x800
@@ -148,6 +153,11 @@
@@ -148,6 +153,11 @@ extern void ltq_pmu_enable(unsigned int
extern void ltq_pmu_disable(unsigned int module);
extern void ltq_cgu_enable(unsigned int clk);
@ -85,11 +81,9 @@ Index: linux-3.0.3/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
static inline int ltq_is_ar9(void)
{
return (ltq_get_soc_type() == SOC_TYPE_AR9);
Index: linux-3.0.3/arch/mips/lantiq/xway/devices.c
===================================================================
--- linux-3.0.3.orig/arch/mips/lantiq/xway/devices.c 2011-10-04 20:03:54.000000000 +0200
+++ linux-3.0.3/arch/mips/lantiq/xway/devices.c 2011-10-04 20:05:44.146312365 +0200
@@ -79,18 +79,23 @@
--- a/arch/mips/lantiq/xway/devices.c
+++ b/arch/mips/lantiq/xway/devices.c
@@ -77,18 +77,23 @@ void __init ltq_register_ase_asc(void)
}
/* ethernet */
@ -116,10 +110,8 @@ Index: linux-3.0.3/arch/mips/lantiq/xway/devices.c
if (eth) {
ltq_etop.dev.platform_data = eth;
platform_device_register(&ltq_etop);
Index: linux-3.0.3/drivers/net/lantiq_etop.c
===================================================================
--- linux-3.0.3.orig/drivers/net/lantiq_etop.c 2011-08-17 19:57:16.000000000 +0200
+++ linux-3.0.3/drivers/net/lantiq_etop.c 2011-10-04 20:05:44.146312365 +0200
--- a/drivers/net/lantiq_etop.c
+++ b/drivers/net/lantiq_etop.c
@@ -34,6 +34,7 @@
#include <linux/init.h>
#include <linux/delay.h>
@ -190,7 +182,7 @@ Index: linux-3.0.3/drivers/net/lantiq_etop.c
struct ltq_etop_chan {
int idx;
@@ -108,6 +148,9 @@
@@ -108,6 +148,9 @@ struct ltq_etop_priv {
spinlock_t lock;
};
@ -200,7 +192,7 @@ Index: linux-3.0.3/drivers/net/lantiq_etop.c
static int
ltq_etop_alloc_skb(struct ltq_etop_chan *ch)
{
@@ -209,7 +252,7 @@
@@ -209,7 +252,7 @@ static irqreturn_t
ltq_etop_dma_irq(int irq, void *_priv)
{
struct ltq_etop_priv *priv = _priv;
@ -209,7 +201,7 @@ Index: linux-3.0.3/drivers/net/lantiq_etop.c
napi_schedule(&priv->ch[ch].napi);
return IRQ_HANDLED;
@@ -242,26 +285,66 @@
@@ -242,26 +285,66 @@ ltq_etop_hw_exit(struct net_device *dev)
ltq_etop_free_channel(dev, &priv->ch[i]);
}
@ -277,7 +269,7 @@ Index: linux-3.0.3/drivers/net/lantiq_etop.c
netdev_err(dev, "unknown mii mode %d\n",
priv->pldata->mii_mode);
return -ENOTSUPP;
@@ -273,7 +356,7 @@
@@ -273,7 +356,7 @@ ltq_etop_hw_init(struct net_device *dev)
ltq_dma_init_port(DMA_PORT_ETOP);
for (i = 0; i < MAX_DMA_CHAN; i++) {
@ -286,7 +278,7 @@ Index: linux-3.0.3/drivers/net/lantiq_etop.c
struct ltq_etop_chan *ch = &priv->ch[i];
ch->idx = ch->dma.nr = i;
@@ -337,6 +420,39 @@
@@ -337,6 +420,39 @@ static const struct ethtool_ops ltq_etop
};
static int
@ -326,7 +318,7 @@ Index: linux-3.0.3/drivers/net/lantiq_etop.c
ltq_etop_mdio_wr(struct mii_bus *bus, int phy_addr, int phy_reg, u16 phy_data)
{
u32 val = MDIO_REQUEST |
@@ -377,14 +493,11 @@
@@ -377,14 +493,11 @@ ltq_etop_mdio_probe(struct net_device *d
{
struct ltq_etop_priv *priv = netdev_priv(dev);
struct phy_device *phydev = NULL;
@ -345,7 +337,7 @@ Index: linux-3.0.3/drivers/net/lantiq_etop.c
if (!phydev) {
netdev_err(dev, "no PHY found\n");
@@ -406,6 +519,9 @@
@@ -406,6 +519,9 @@ ltq_etop_mdio_probe(struct net_device *d
| SUPPORTED_Autoneg
| SUPPORTED_MII
| SUPPORTED_TP);
@ -355,7 +347,7 @@ Index: linux-3.0.3/drivers/net/lantiq_etop.c
phydev->advertising = phydev->supported;
priv->phydev = phydev;
@@ -431,8 +547,13 @@
@@ -431,8 +547,13 @@ ltq_etop_mdio_init(struct net_device *de
}
priv->mii_bus->priv = dev;
@ -371,7 +363,7 @@ Index: linux-3.0.3/drivers/net/lantiq_etop.c
priv->mii_bus->name = "ltq_mii";
snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%x", 0);
priv->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
@@ -522,9 +643,9 @@
@@ -522,9 +643,9 @@ ltq_etop_tx(struct sk_buff *skb, struct
struct ltq_etop_priv *priv = netdev_priv(dev);
struct ltq_etop_chan *ch = &priv->ch[(queue << 1) | 1];
struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
@ -382,7 +374,7 @@ Index: linux-3.0.3/drivers/net/lantiq_etop.c
len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
@@ -698,7 +819,7 @@
@@ -698,7 +819,7 @@ ltq_etop_probe(struct platform_device *p
{
struct net_device *dev;
struct ltq_etop_priv *priv;
@ -391,7 +383,7 @@ Index: linux-3.0.3/drivers/net/lantiq_etop.c
int err;
int i;
@@ -726,6 +847,23 @@
@@ -726,6 +847,23 @@ ltq_etop_probe(struct platform_device *p
goto err_out;
}

View File

@ -24,8 +24,6 @@ TODO : memory ranges
5 files changed, 190 insertions(+), 1 deletions(-)
create mode 100644 arch/mips/lantiq/xway/nand.c
diff --git a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
index 86ed0d2..729dfa2 100644
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
@@ -140,6 +140,8 @@
@ -37,8 +35,6 @@ index 86ed0d2..729dfa2 100644
#define ltq_cgu_w32(x, y) ltq_w32((x), ltq_cgu_membase + (y))
#define ltq_cgu_r32(x) ltq_r32(ltq_cgu_membase + (x))
diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
index 6678402..ac7cc34 100644
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -1,4 +1,4 @@
@ -47,9 +43,6 @@ index 6678402..ac7cc34 100644
obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o
obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o
diff --git a/arch/mips/lantiq/xway/nand.c b/arch/mips/lantiq/xway/nand.c
new file mode 100644
index 0000000..ba2443c
--- /dev/null
+++ b/arch/mips/lantiq/xway/nand.c
@@ -0,0 +1,185 @@
@ -238,11 +231,9 @@ index 0000000..ba2443c
+{
+ platform_device_register(&ltq_flash_nand);
+}
diff --git a/drivers/mtd/nand/plat_nand.c b/drivers/mtd/nand/plat_nand.c
index 633c04b..c3e3ef6 100644
--- a/drivers/mtd/nand/plat_nand.c
+++ b/drivers/mtd/nand/plat_nand.c
@@ -77,6 +77,7 @@ static int __devinit plat_nand_probe(struct platform_device *pdev)
@@ -77,6 +77,7 @@ static int __devinit plat_nand_probe(str
data->chip.select_chip = pdata->ctrl.select_chip;
data->chip.write_buf = pdata->ctrl.write_buf;
data->chip.read_buf = pdata->ctrl.read_buf;
@ -250,11 +241,9 @@ index 633c04b..c3e3ef6 100644
data->chip.chip_delay = pdata->chip.chip_delay;
data->chip.options |= pdata->chip.options;
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index c2b9ac4..597e1a0 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -656,6 +656,7 @@ struct platform_nand_ctrl {
@@ -657,6 +657,7 @@ struct platform_nand_ctrl {
void (*cmd_ctrl)(struct mtd_info *mtd, int dat, unsigned int ctrl);
void (*write_buf)(struct mtd_info *mtd, const uint8_t *buf, int len);
void (*read_buf)(struct mtd_info *mtd, uint8_t *buf, int len);
@ -262,6 +251,3 @@ index c2b9ac4..597e1a0 100644
void *priv;
};
--
1.7.5.4

View File

@ -11,9 +11,6 @@ Subject: [PATCH 17/24] MIPS: lantiq: adds GPTU driver
create mode 100644 arch/mips/include/asm/mach-lantiq/lantiq_timer.h
create mode 100644 arch/mips/lantiq/xway/timer.c
diff --git a/arch/mips/include/asm/mach-lantiq/lantiq_timer.h b/arch/mips/include/asm/mach-lantiq/lantiq_timer.h
new file mode 100644
index 0000000..ef564ab
--- /dev/null
+++ b/arch/mips/include/asm/mach-lantiq/lantiq_timer.h
@@ -0,0 +1,155 @@
@ -172,8 +169,6 @@ index 0000000..ef564ab
+ u32 reload, unsigned long arg1, unsigned long arg2);
+
+#endif /* __DANUBE_GPTU_DEV_H__2005_07_26__10_19__ */
diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
index ac7cc34..1f41239 100644
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -1,4 +1,4 @@
@ -182,9 +177,6 @@ index ac7cc34..1f41239 100644
obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o
obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o
diff --git a/arch/mips/lantiq/xway/timer.c b/arch/mips/lantiq/xway/timer.c
new file mode 100644
index 0000000..cac2ea8
--- /dev/null
+++ b/arch/mips/lantiq/xway/timer.c
@@ -0,0 +1,830 @@
@ -1018,6 +1010,3 @@ index 0000000..cac2ea8
+
+module_init(lq_gptu_init);
+module_exit(lq_gptu_exit);
--
1.7.5.4

View File

@ -45,8 +45,6 @@ Subject: [PATCH 18/24] MIPS: lantiq: adds dwc_otg
create mode 100644 drivers/usb/dwc_otg/dwc_otg_plat.h
create mode 100644 drivers/usb/dwc_otg/dwc_otg_regs.h
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 48f1781..b48c1bd 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -116,6 +116,8 @@ source "drivers/usb/wusbcore/Kconfig"
@ -58,8 +56,6 @@ index 48f1781..b48c1bd 100644
source "drivers/usb/musb/Kconfig"
source "drivers/usb/renesas_usbhs/Kconfig"
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile
index 30ddf8d..ba3b993 100644
--- a/drivers/usb/Makefile
+++ b/drivers/usb/Makefile
@@ -28,6 +28,8 @@ obj-$(CONFIG_USB_C67X00_HCD) += c67x00/
@ -71,11 +67,9 @@ index 30ddf8d..ba3b993 100644
obj-$(CONFIG_USB_ACM) += class/
obj-$(CONFIG_USB_PRINTER) += class/
obj-$(CONFIG_USB_WDM) += class/
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index a428aa0..115ae9a 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -2885,11 +2885,11 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1,
@@ -2885,11 +2885,11 @@ hub_port_init (struct usb_hub *hub, stru
udev->ttport = hdev->ttport;
} else if (udev->speed != USB_SPEED_HIGH
&& hdev->speed == USB_SPEED_HIGH) {
@ -89,9 +83,6 @@ index a428aa0..115ae9a 100644
udev->tt = &hub->tt;
udev->ttport = port1;
}
diff --git a/drivers/usb/dwc_otg/Kconfig b/drivers/usb/dwc_otg/Kconfig
new file mode 100644
index 0000000..e018490
--- /dev/null
+++ b/drivers/usb/dwc_otg/Kconfig
@@ -0,0 +1,37 @@
@ -132,9 +123,6 @@ index 0000000..e018490
+config DWC_OTG_DEBUG
+ bool "Enable debug mode"
+ depends on DWC_OTG
diff --git a/drivers/usb/dwc_otg/Makefile b/drivers/usb/dwc_otg/Makefile
new file mode 100644
index 0000000..d4d2355
--- /dev/null
+++ b/drivers/usb/dwc_otg/Makefile
@@ -0,0 +1,39 @@
@ -177,9 +165,6 @@ index 0000000..d4d2355
+
+#obj-$(CONFIG_DWC_OTG_IFX) := dwc_otg_ifx.o
+#dwc_otg_ifx-objs := dwc_otg_ifx.o
diff --git a/drivers/usb/dwc_otg/dwc_otg_attr.c b/drivers/usb/dwc_otg/dwc_otg_attr.c
new file mode 100644
index 0000000..4675a5c
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_attr.c
@@ -0,0 +1,802 @@
@ -985,9 +970,6 @@ index 0000000..4675a5c
+ device_remove_file(_dev, &dev_attr_rd_reg_test);
+ device_remove_file(_dev, &dev_attr_wr_reg_test);
+}
diff --git a/drivers/usb/dwc_otg/dwc_otg_attr.h b/drivers/usb/dwc_otg/dwc_otg_attr.h
new file mode 100644
index 0000000..4bbf7df
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_attr.h
@@ -0,0 +1,67 @@
@ -1058,9 +1040,6 @@ index 0000000..4bbf7df
+void dwc_otg_attr_remove (struct device *_dev);
+
+#endif
diff --git a/drivers/usb/dwc_otg/dwc_otg_cil.c b/drivers/usb/dwc_otg/dwc_otg_cil.c
new file mode 100644
index 0000000..42c69eb
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_cil.c
@@ -0,0 +1,3025 @@
@ -4089,9 +4068,6 @@ index 0000000..42c69eb
+ _cb->p = _p;
+}
+
diff --git a/drivers/usb/dwc_otg/dwc_otg_cil.h b/drivers/usb/dwc_otg/dwc_otg_cil.h
new file mode 100644
index 0000000..bbb9516
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_cil.h
@@ -0,0 +1,911 @@
@ -5006,9 +4982,6 @@ index 0000000..bbb9516
+
+
+#endif
diff --git a/drivers/usb/dwc_otg/dwc_otg_cil_ifx.h b/drivers/usb/dwc_otg/dwc_otg_cil_ifx.h
new file mode 100644
index 0000000..b0298ec
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_cil_ifx.h
@@ -0,0 +1,58 @@
@ -5070,9 +5043,6 @@ index 0000000..b0298ec
+
+#endif // __DWC_OTG_CIL_IFX_H__
+
diff --git a/drivers/usb/dwc_otg/dwc_otg_cil_intr.c b/drivers/usb/dwc_otg/dwc_otg_cil_intr.c
new file mode 100644
index 0000000..d469ab4
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_cil_intr.c
@@ -0,0 +1,708 @@
@ -5784,9 +5754,6 @@ index 0000000..d469ab4
+ }
+ return retval;
+}
diff --git a/drivers/usb/dwc_otg/dwc_otg_driver.c b/drivers/usb/dwc_otg/dwc_otg_driver.c
new file mode 100644
index 0000000..1b0daab
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_driver.c
@@ -0,0 +1,1274 @@
@ -7064,9 +7031,6 @@ index 0000000..1b0daab
+ </td></tr>
+
+*/
diff --git a/drivers/usb/dwc_otg/dwc_otg_driver.h b/drivers/usb/dwc_otg/dwc_otg_driver.h
new file mode 100644
index 0000000..7e6940d
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_driver.h
@@ -0,0 +1,84 @@
@ -7154,9 +7118,6 @@ index 0000000..7e6940d
+//#define dev_dbg(fake, format, arg...) printk(KERN_CRIT __FILE__ ":%d: " format "\n" , __LINE__, ## arg)
+
+#endif
diff --git a/drivers/usb/dwc_otg/dwc_otg_hcd.c b/drivers/usb/dwc_otg/dwc_otg_hcd.c
new file mode 100644
index 0000000..ad6bc72
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_hcd.c
@@ -0,0 +1,2870 @@
@ -10030,9 +9991,6 @@ index 0000000..ad6bc72
+#endif
+}
+#endif /* DWC_DEVICE_ONLY */
diff --git a/drivers/usb/dwc_otg/dwc_otg_hcd.h b/drivers/usb/dwc_otg/dwc_otg_hcd.h
new file mode 100644
index 0000000..8a20dff
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_hcd.h
@@ -0,0 +1,676 @@
@ -10712,9 +10670,6 @@ index 0000000..8a20dff
+#endif // DEBUG
+#endif // __DWC_HCD_H__
+#endif /* DWC_DEVICE_ONLY */
diff --git a/drivers/usb/dwc_otg/dwc_otg_hcd_intr.c b/drivers/usb/dwc_otg/dwc_otg_hcd_intr.c
new file mode 100644
index 0000000..834b5e0
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_hcd_intr.c
@@ -0,0 +1,1841 @@
@ -12559,9 +12514,6 @@ index 0000000..834b5e0
+}
+
+#endif /* DWC_DEVICE_ONLY */
diff --git a/drivers/usb/dwc_otg/dwc_otg_hcd_queue.c b/drivers/usb/dwc_otg/dwc_otg_hcd_queue.c
new file mode 100644
index 0000000..fcb5ce6
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_hcd_queue.c
@@ -0,0 +1,794 @@
@ -13359,9 +13311,6 @@ index 0000000..fcb5ce6
+}
+
+#endif /* DWC_DEVICE_ONLY */
diff --git a/drivers/usb/dwc_otg/dwc_otg_ifx.c b/drivers/usb/dwc_otg/dwc_otg_ifx.c
new file mode 100644
index 0000000..0a4c209
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_ifx.c
@@ -0,0 +1,100 @@
@ -13465,9 +13414,6 @@ index 0000000..0a4c209
+void ifx_usb_hc_remove(void)
+{
+}
diff --git a/drivers/usb/dwc_otg/dwc_otg_ifx.h b/drivers/usb/dwc_otg/dwc_otg_ifx.h
new file mode 100644
index 0000000..402d7a6
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_ifx.h
@@ -0,0 +1,85 @@
@ -13556,9 +13502,6 @@ index 0000000..402d7a6
+ ltq_mask_and_ack_irq(&d);
+}
+#endif //__DWC_OTG_IFX_H__
diff --git a/drivers/usb/dwc_otg/dwc_otg_plat.h b/drivers/usb/dwc_otg/dwc_otg_plat.h
new file mode 100644
index 0000000..727d0c4
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_plat.h
@@ -0,0 +1,269 @@
@ -13831,9 +13774,6 @@ index 0000000..727d0c4
+
+#endif
+
diff --git a/drivers/usb/dwc_otg/dwc_otg_regs.h b/drivers/usb/dwc_otg/dwc_otg_regs.h
new file mode 100644
index 0000000..397a954
--- /dev/null
+++ b/drivers/usb/dwc_otg/dwc_otg_regs.h
@@ -0,0 +1,1797 @@
@ -15634,6 +15574,3 @@ index 0000000..397a954
+} dwc_otg_host_if_t;
+
+#endif
--
1.7.5.4

View File

@ -1,6 +1,25 @@
From c6c810d83f0d95f54c3a6b338d219cec7ccef4c9 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 29 Sep 2011 20:30:40 +0200
Subject: [PATCH 19/24] MIPS: lantiq: adds VPE extensions
---
arch/mips/Kconfig | 22 +++
arch/mips/include/asm/mipsmtregs.h | 54 +++++++
arch/mips/kernel/Makefile | 3 +-
arch/mips/kernel/mips-mt.c | 97 +++++++++++--
arch/mips/kernel/mtsched_proc.c | 279 ++++++++++++++++++++++++++++++++++++
arch/mips/kernel/perf_proc.c | 191 ++++++++++++++++++++++++
arch/mips/kernel/proc.c | 17 +++
arch/mips/kernel/smtc.c | 7 +
arch/mips/kernel/vpe.c | 250 ++++++++++++++++++++++++++++++++-
9 files changed, 905 insertions(+), 15 deletions(-)
create mode 100644 arch/mips/kernel/mtsched_proc.c
create mode 100644 arch/mips/kernel/perf_proc.c
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1871,6 +1871,28 @@ config MIPS_VPE_LOADER
@@ -1915,6 +1915,28 @@ config MIPS_VPE_LOADER
Includes a loader for loading an elf relocatable object
onto another VPE and running it.
@ -140,7 +159,7 @@
#define read_tc_gpr_sp() mftgpr(29)
--- a/arch/mips/kernel/Makefile
+++ b/arch/mips/kernel/Makefile
@@ -85,7 +85,8 @@ obj-$(CONFIG_MIPS32_O32) += binfmt_elfo3
@@ -86,7 +86,8 @@ obj-$(CONFIG_MIPS32_O32) += binfmt_elfo3
obj-$(CONFIG_KGDB) += kgdb.o
obj-$(CONFIG_PROC_FS) += proc.o
@ -290,417 +309,6 @@
}
/*
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -7,6 +7,7 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/seq_file.h>
+#include <linux/proc_fs.h>
#include <asm/bootinfo.h>
#include <asm/cpu.h>
#include <asm/cpu-features.h>
@@ -110,3 +111,19 @@ const struct seq_operations cpuinfo_op =
.stop = c_stop,
.show = show_cpuinfo,
};
+
+/*
+ * Support for MIPS/local /proc hooks in /proc/mips/
+ */
+
+static struct proc_dir_entry *mips_proc = NULL;
+
+struct proc_dir_entry *get_mips_proc_dir(void)
+{
+ /*
+ * This ought not to be preemptable.
+ */
+ if(mips_proc == NULL)
+ mips_proc = proc_mkdir("mips", NULL);
+ return(mips_proc);
+}
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -1334,6 +1334,13 @@ void smtc_get_new_mmu_context(struct mm_
asid = asid_cache(cpu);
do {
+#ifdef CONFIG_IFX_VPE_EXT
+ /* If TLB is shared between AP and RP (AP is running SMTC),
+ leave out max ASID i.e., ASID_MASK for RP
+ */
+ if (!nostlb && ((asid & ASID_MASK) == (ASID_MASK - 1)))
+ asid++;
+#endif
if (!((asid += ASID_INC) & ASID_MASK) ) {
if (cpu_has_vtag_icache)
flush_icache_all();
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -76,6 +76,58 @@ static struct kspd_notifications kspd_ev
static int kspd_events_reqd;
#endif
+#ifdef CONFIG_IFX_VPE_EXT
+static int is_sdepgm;
+extern int stlb;
+extern int vpe0_wired;
+extern int vpe1_wired;
+unsigned int vpe1_load_addr;
+
+static int __init load_address(char *str)
+{
+ get_option(&str, &vpe1_load_addr);
+ return 1;
+}
+__setup("vpe1_load_addr=", load_address);
+
+#include <asm/mipsmtregs.h>
+#define write_vpe_c0_wired(val) mttc0(6, 0, val)
+
+#ifndef COMMAND_LINE_SIZE
+# define COMMAND_LINE_SIZE 512
+#endif
+
+char command_line[COMMAND_LINE_SIZE * 2];
+
+static unsigned int vpe1_mem;
+static int __init vpe1mem(char *str)
+{
+ vpe1_mem = memparse(str, &str);
+ return 1;
+}
+__setup("vpe1_mem=", vpe1mem);
+
+uint32_t vpe1_wdog_ctr;
+static int __init wdog_ctr(char *str)
+{
+ get_option(&str, &vpe1_wdog_ctr);
+ return 1;
+}
+
+__setup("vpe1_wdog_ctr_addr=", wdog_ctr);
+EXPORT_SYMBOL(vpe1_wdog_ctr);
+
+uint32_t vpe1_wdog_timeout;
+static int __init wdog_timeout(char *str)
+{
+ get_option(&str, &vpe1_wdog_timeout);
+ return 1;
+}
+
+__setup("vpe1_wdog_timeout=", wdog_timeout);
+EXPORT_SYMBOL(vpe1_wdog_timeout);
+
+#endif
/* grab the likely amount of memory we will need. */
#ifdef CONFIG_MIPS_VPE_LOADER_TOM
#define P_SIZE (2 * 1024 * 1024)
@@ -268,6 +320,13 @@ static void *alloc_progmem(unsigned long
void *addr;
#ifdef CONFIG_MIPS_VPE_LOADER_TOM
+#ifdef CONFIG_IFX_VPE_EXT
+ if (vpe1_load_addr) {
+ memset((void *)vpe1_load_addr, 0, len);
+ return (void *)vpe1_load_addr;
+ }
+#endif
+
/*
* This means you must tell Linux to use less memory than you
* physically have, for example by passing a mem= boot argument.
@@ -746,6 +805,12 @@ static int vpe_run(struct vpe * v)
}
/* Write the address we want it to start running from in the TCPC register. */
+#if defined(CONFIG_IFX_VPE_EXT) && 0
+ if (stlb)
+ write_vpe_c0_wired(vpe0_wired + vpe1_wired);
+ else
+ write_vpe_c0_wired(vpe1_wired);
+#endif
write_tc_c0_tcrestart((unsigned long)v->__start);
write_tc_c0_tccontext((unsigned long)0);
@@ -759,6 +824,20 @@ static int vpe_run(struct vpe * v)
write_tc_c0_tchalt(read_tc_c0_tchalt() & ~TCHALT_H);
+#if defined(CONFIG_IFX_VPE_EXT) && 0
+ /*
+ * $a2 & $a3 are used to pass command line parameters to VPE1. $a2
+ * points to the start of the command line string and $a3 points to
+ * the end of the string. This convention is identical to the Linux
+ * kernel boot parameter passing mechanism. Please note that $a3 is
+ * used to pass physical memory size or 0 in SDE tool kit. So, if you
+ * are passing comand line parameters through $a2 & $a3 SDE programs
+ * don't work as desired.
+ */
+ mttgpr(6, command_line);
+ mttgpr(7, (command_line + strlen(command_line)));
+ if (is_sdepgm)
+#endif
/*
* The sde-kit passes 'memsize' to __start in $a3, so set something
* here... Or set $a3 to zero and define DFLT_STACK_SIZE and
@@ -833,6 +912,9 @@ static int find_vpe_symbols(struct vpe *
if ( (v->__start == 0) || (v->shared_ptr == NULL))
return -1;
+#ifdef CONFIG_IFX_VPE_EXT
+ is_sdepgm = 1;
+#endif
return 0;
}
@@ -994,6 +1076,15 @@ static int vpe_elfload(struct vpe * v)
(unsigned long)v->load_addr + v->len);
if ((find_vpe_symbols(v, sechdrs, symindex, strtab, &mod)) < 0) {
+#ifdef CONFIG_IFX_VPE_EXT
+ if (vpe1_load_addr) {
+ /* Conversion to KSEG1 is required ??? */
+ v->__start = KSEG1ADDR(vpe1_load_addr);
+ is_sdepgm = 0;
+ return 0;
+ }
+#endif
+
if (v->__start == 0) {
printk(KERN_WARNING "VPE loader: program does not contain "
"a __start symbol\n");
@@ -1064,6 +1155,9 @@ static int vpe_open(struct inode *inode,
struct vpe_notifications *not;
struct vpe *v;
int ret;
+#ifdef CONFIG_IFX_VPE_EXT
+ int progsize;
+#endif
if (minor != iminor(inode)) {
/* assume only 1 device at the moment. */
@@ -1089,7 +1183,12 @@ static int vpe_open(struct inode *inode,
release_progmem(v->load_addr);
cleanup_tc(get_tc(tclimit));
}
-
+#ifdef CONFIG_IFX_VPE_EXT
+ progsize = (vpe1_mem != 0) ? vpe1_mem : P_SIZE;
+ //printk("progsize = %x\n", progsize);
+ v->pbuffer = vmalloc(progsize);
+ v->plen = progsize;
+#else
/* this of-course trashes what was there before... */
v->pbuffer = vmalloc(P_SIZE);
if (!v->pbuffer) {
@@ -1097,11 +1196,14 @@ static int vpe_open(struct inode *inode,
return -ENOMEM;
}
v->plen = P_SIZE;
+#endif
v->load_addr = NULL;
v->len = 0;
+#if 0
v->uid = filp->f_cred->fsuid;
v->gid = filp->f_cred->fsgid;
+#endif
#ifdef CONFIG_MIPS_APSP_KSPD
/* get kspd to tell us when a syscall_exit happens */
@@ -1349,6 +1451,133 @@ static void kspd_sp_exit( int sp_id)
cleanup_tc(get_tc(sp_id));
}
#endif
+#ifdef CONFIG_IFX_VPE_EXT
+int32_t vpe1_sw_start(void* sw_start_addr, uint32_t tcmask, uint32_t flags)
+{
+ enum vpe_state state;
+ struct vpe *v = get_vpe(tclimit);
+ struct vpe_notifications *not;
+
+ if (tcmask || flags) {
+ printk(KERN_WARNING "Currently tcmask and flags should be 0.\
+ other values not supported\n");
+ return -1;
+ }
+
+ state = xchg(&v->state, VPE_STATE_INUSE);
+ if (state != VPE_STATE_UNUSED) {
+ vpe_stop(v);
+
+ list_for_each_entry(not, &v->notify, list) {
+ not->stop(tclimit);
+ }
+ }
+
+ v->__start = (unsigned long)sw_start_addr;
+ is_sdepgm = 0;
+
+ if (!vpe_run(v)) {
+ printk(KERN_DEBUG "VPE loader: VPE1 running successfully\n");
+ return 0;
+ }
+ return -1;
+}
+
+EXPORT_SYMBOL(vpe1_sw_start);
+
+int32_t vpe1_sw_stop(uint32_t flags)
+{
+ struct vpe *v = get_vpe(tclimit);
+
+ if (!vpe_free(v)) {
+ printk(KERN_DEBUG "RP Stopped\n");
+ return 0;
+ }
+ else
+ return -1;
+}
+
+EXPORT_SYMBOL(vpe1_sw_stop);
+
+uint32_t vpe1_get_load_addr (uint32_t flags)
+{
+ return vpe1_load_addr;
+}
+
+EXPORT_SYMBOL(vpe1_get_load_addr);
+
+uint32_t vpe1_get_max_mem (uint32_t flags)
+{
+ if (!vpe1_mem)
+ return P_SIZE;
+ else
+ return vpe1_mem;
+}
+
+EXPORT_SYMBOL(vpe1_get_max_mem);
+
+void* vpe1_get_cmdline_argument(void)
+{
+ return saved_command_line;
+}
+
+EXPORT_SYMBOL(vpe1_get_cmdline_argument);
+
+int32_t vpe1_set_boot_param(char *field, char *value, char flags)
+{
+ char *ptr, string[64];
+ int start_off, end_off;
+ if (!field)
+ return -1;
+ strcpy(string, field);
+ if (value) {
+ strcat(string, "=");
+ strcat(string, value);
+ strcat(command_line, " ");
+ strcat(command_line, string);
+ }
+ else {
+ ptr = strstr(command_line, string);
+ if (ptr) {
+ start_off = ptr - command_line;
+ ptr += strlen(string);
+ while ((*ptr != ' ') && (*ptr != '\0'))
+ ptr++;
+ end_off = ptr - command_line;
+ command_line[start_off] = '\0';
+ strcat (command_line, command_line+end_off);
+ }
+ }
+ return 0;
+}
+
+EXPORT_SYMBOL(vpe1_set_boot_param);
+
+int32_t vpe1_get_boot_param(char *field, char **value, char flags)
+{
+ char *ptr, string[64];
+ int i = 0;
+ if (!field)
+ return -1;
+ if ((ptr = strstr(command_line, field))) {
+ ptr += strlen(field) + 1; /* including = */
+ while ((*ptr != ' ') && (*ptr != '\0'))
+ string[i++] = *ptr++;
+ string[i] = '\0';
+ *value = kmalloc((strlen(string) + 1), GFP_KERNEL);
+ if (*value != NULL)
+ strcpy(*value, string);
+ }
+ else
+ *value = NULL;
+
+ return 0;
+}
+
+EXPORT_SYMBOL(vpe1_get_boot_param);
+
+extern void configure_tlb(void);
+#endif
static ssize_t store_kill(struct device *dev, struct device_attribute *attr,
const char *buf, size_t len)
@@ -1430,6 +1659,18 @@ static int __init vpe_module_init(void)
printk("VPE loader: not a MIPS MT capable processor\n");
return -ENODEV;
}
+#ifdef CONFIG_IFX_VPE_EXT
+#ifndef CONFIG_MIPS_MT_SMTC
+ configure_tlb();
+#endif
+#endif
+
+#ifndef CONFIG_MIPS_MT_SMTC
+ if (!vpelimit)
+ vpelimit = 1;
+ if (!tclimit)
+ tclimit = 1;
+#endif
if (vpelimit == 0) {
printk(KERN_WARNING "No VPEs reserved for AP/SP, not "
@@ -1474,10 +1715,12 @@ static int __init vpe_module_init(void)
mtflags = dmt();
vpflags = dvpe();
+ back_to_back_c0_hazard();
+
/* Put MVPE's into 'configuration state' */
set_c0_mvpcontrol(MVPCONTROL_VPC);
- /* dump_mtregs(); */
+ dump_mtregs();
val = read_c0_mvpconf0();
hw_tcs = (val & MVPCONF0_PTC) + 1;
@@ -1489,6 +1732,7 @@ static int __init vpe_module_init(void)
* reschedule send IPIs or similar we might hang.
*/
clear_c0_mvpcontrol(MVPCONTROL_VPC);
+ back_to_back_c0_hazard();
evpe(vpflags);
emt(mtflags);
local_irq_restore(flags);
@@ -1514,6 +1758,7 @@ static int __init vpe_module_init(void)
}
v->ntcs = hw_tcs - tclimit;
+ write_tc_c0_tcbind((read_tc_c0_tcbind() & ~TCBIND_CURVPE) | 1);
/* add the tc to the list of this vpe's tc's. */
list_add(&t->tc, &v->tc);
@@ -1582,6 +1827,7 @@ static int __init vpe_module_init(void)
out_reenable:
/* release config state */
clear_c0_mvpcontrol(MVPCONTROL_VPC);
+ back_to_back_c0_hazard();
evpe(vpflags);
emt(mtflags);
--- /dev/null
+++ b/arch/mips/kernel/mtsched_proc.c
@@ -0,0 +1,279 @@
@ -1177,3 +785,414 @@
+
+/* Automagically create the entry */
+module_init(init_perf_proc);
--- a/arch/mips/kernel/proc.c
+++ b/arch/mips/kernel/proc.c
@@ -7,6 +7,7 @@
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/seq_file.h>
+#include <linux/proc_fs.h>
#include <asm/bootinfo.h>
#include <asm/cpu.h>
#include <asm/cpu-features.h>
@@ -110,3 +111,19 @@ const struct seq_operations cpuinfo_op =
.stop = c_stop,
.show = show_cpuinfo,
};
+
+/*
+ * Support for MIPS/local /proc hooks in /proc/mips/
+ */
+
+static struct proc_dir_entry *mips_proc = NULL;
+
+struct proc_dir_entry *get_mips_proc_dir(void)
+{
+ /*
+ * This ought not to be preemptable.
+ */
+ if(mips_proc == NULL)
+ mips_proc = proc_mkdir("mips", NULL);
+ return(mips_proc);
+}
--- a/arch/mips/kernel/smtc.c
+++ b/arch/mips/kernel/smtc.c
@@ -1334,6 +1334,13 @@ void smtc_get_new_mmu_context(struct mm_
asid = asid_cache(cpu);
do {
+#ifdef CONFIG_IFX_VPE_EXT
+ /* If TLB is shared between AP and RP (AP is running SMTC),
+ leave out max ASID i.e., ASID_MASK for RP
+ */
+ if (!nostlb && ((asid & ASID_MASK) == (ASID_MASK - 1)))
+ asid++;
+#endif
if (!((asid += ASID_INC) & ASID_MASK) ) {
if (cpu_has_vtag_icache)
flush_icache_all();
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -76,6 +76,58 @@ static struct kspd_notifications kspd_ev
static int kspd_events_reqd;
#endif
+#ifdef CONFIG_IFX_VPE_EXT
+static int is_sdepgm;
+extern int stlb;
+extern int vpe0_wired;
+extern int vpe1_wired;
+unsigned int vpe1_load_addr;
+
+static int __init load_address(char *str)
+{
+ get_option(&str, &vpe1_load_addr);
+ return 1;
+}
+__setup("vpe1_load_addr=", load_address);
+
+#include <asm/mipsmtregs.h>
+#define write_vpe_c0_wired(val) mttc0(6, 0, val)
+
+#ifndef COMMAND_LINE_SIZE
+# define COMMAND_LINE_SIZE 512
+#endif
+
+char command_line[COMMAND_LINE_SIZE * 2];
+
+static unsigned int vpe1_mem;
+static int __init vpe1mem(char *str)
+{
+ vpe1_mem = memparse(str, &str);
+ return 1;
+}
+__setup("vpe1_mem=", vpe1mem);
+
+uint32_t vpe1_wdog_ctr;
+static int __init wdog_ctr(char *str)
+{
+ get_option(&str, &vpe1_wdog_ctr);
+ return 1;
+}
+
+__setup("vpe1_wdog_ctr_addr=", wdog_ctr);
+EXPORT_SYMBOL(vpe1_wdog_ctr);
+
+uint32_t vpe1_wdog_timeout;
+static int __init wdog_timeout(char *str)
+{
+ get_option(&str, &vpe1_wdog_timeout);
+ return 1;
+}
+
+__setup("vpe1_wdog_timeout=", wdog_timeout);
+EXPORT_SYMBOL(vpe1_wdog_timeout);
+
+#endif
/* grab the likely amount of memory we will need. */
#ifdef CONFIG_MIPS_VPE_LOADER_TOM
#define P_SIZE (2 * 1024 * 1024)
@@ -268,6 +320,13 @@ static void *alloc_progmem(unsigned long
void *addr;
#ifdef CONFIG_MIPS_VPE_LOADER_TOM
+#ifdef CONFIG_IFX_VPE_EXT
+ if (vpe1_load_addr) {
+ memset((void *)vpe1_load_addr, 0, len);
+ return (void *)vpe1_load_addr;
+ }
+#endif
+
/*
* This means you must tell Linux to use less memory than you
* physically have, for example by passing a mem= boot argument.
@@ -746,6 +805,12 @@ static int vpe_run(struct vpe * v)
}
/* Write the address we want it to start running from in the TCPC register. */
+#if defined(CONFIG_IFX_VPE_EXT) && 0
+ if (stlb)
+ write_vpe_c0_wired(vpe0_wired + vpe1_wired);
+ else
+ write_vpe_c0_wired(vpe1_wired);
+#endif
write_tc_c0_tcrestart((unsigned long)v->__start);
write_tc_c0_tccontext((unsigned long)0);
@@ -759,6 +824,20 @@ static int vpe_run(struct vpe * v)
write_tc_c0_tchalt(read_tc_c0_tchalt() & ~TCHALT_H);
+#if defined(CONFIG_IFX_VPE_EXT) && 0
+ /*
+ * $a2 & $a3 are used to pass command line parameters to VPE1. $a2
+ * points to the start of the command line string and $a3 points to
+ * the end of the string. This convention is identical to the Linux
+ * kernel boot parameter passing mechanism. Please note that $a3 is
+ * used to pass physical memory size or 0 in SDE tool kit. So, if you
+ * are passing comand line parameters through $a2 & $a3 SDE programs
+ * don't work as desired.
+ */
+ mttgpr(6, command_line);
+ mttgpr(7, (command_line + strlen(command_line)));
+ if (is_sdepgm)
+#endif
/*
* The sde-kit passes 'memsize' to __start in $a3, so set something
* here... Or set $a3 to zero and define DFLT_STACK_SIZE and
@@ -833,6 +912,9 @@ static int find_vpe_symbols(struct vpe *
if ( (v->__start == 0) || (v->shared_ptr == NULL))
return -1;
+#ifdef CONFIG_IFX_VPE_EXT
+ is_sdepgm = 1;
+#endif
return 0;
}
@@ -994,6 +1076,15 @@ static int vpe_elfload(struct vpe * v)
(unsigned long)v->load_addr + v->len);
if ((find_vpe_symbols(v, sechdrs, symindex, strtab, &mod)) < 0) {
+#ifdef CONFIG_IFX_VPE_EXT
+ if (vpe1_load_addr) {
+ /* Conversion to KSEG1 is required ??? */
+ v->__start = KSEG1ADDR(vpe1_load_addr);
+ is_sdepgm = 0;
+ return 0;
+ }
+#endif
+
if (v->__start == 0) {
printk(KERN_WARNING "VPE loader: program does not contain "
"a __start symbol\n");
@@ -1064,6 +1155,9 @@ static int vpe_open(struct inode *inode,
struct vpe_notifications *not;
struct vpe *v;
int ret;
+#ifdef CONFIG_IFX_VPE_EXT
+ int progsize;
+#endif
if (minor != iminor(inode)) {
/* assume only 1 device at the moment. */
@@ -1089,7 +1183,12 @@ static int vpe_open(struct inode *inode,
release_progmem(v->load_addr);
cleanup_tc(get_tc(tclimit));
}
-
+#ifdef CONFIG_IFX_VPE_EXT
+ progsize = (vpe1_mem != 0) ? vpe1_mem : P_SIZE;
+ //printk("progsize = %x\n", progsize);
+ v->pbuffer = vmalloc(progsize);
+ v->plen = progsize;
+#else
/* this of-course trashes what was there before... */
v->pbuffer = vmalloc(P_SIZE);
if (!v->pbuffer) {
@@ -1097,11 +1196,14 @@ static int vpe_open(struct inode *inode,
return -ENOMEM;
}
v->plen = P_SIZE;
+#endif
v->load_addr = NULL;
v->len = 0;
+#if 0
v->uid = filp->f_cred->fsuid;
v->gid = filp->f_cred->fsgid;
+#endif
#ifdef CONFIG_MIPS_APSP_KSPD
/* get kspd to tell us when a syscall_exit happens */
@@ -1349,6 +1451,133 @@ static void kspd_sp_exit( int sp_id)
cleanup_tc(get_tc(sp_id));
}
#endif
+#ifdef CONFIG_IFX_VPE_EXT
+int32_t vpe1_sw_start(void* sw_start_addr, uint32_t tcmask, uint32_t flags)
+{
+ enum vpe_state state;
+ struct vpe *v = get_vpe(tclimit);
+ struct vpe_notifications *not;
+
+ if (tcmask || flags) {
+ printk(KERN_WARNING "Currently tcmask and flags should be 0.\
+ other values not supported\n");
+ return -1;
+ }
+
+ state = xchg(&v->state, VPE_STATE_INUSE);
+ if (state != VPE_STATE_UNUSED) {
+ vpe_stop(v);
+
+ list_for_each_entry(not, &v->notify, list) {
+ not->stop(tclimit);
+ }
+ }
+
+ v->__start = (unsigned long)sw_start_addr;
+ is_sdepgm = 0;
+
+ if (!vpe_run(v)) {
+ printk(KERN_DEBUG "VPE loader: VPE1 running successfully\n");
+ return 0;
+ }
+ return -1;
+}
+
+EXPORT_SYMBOL(vpe1_sw_start);
+
+int32_t vpe1_sw_stop(uint32_t flags)
+{
+ struct vpe *v = get_vpe(tclimit);
+
+ if (!vpe_free(v)) {
+ printk(KERN_DEBUG "RP Stopped\n");
+ return 0;
+ }
+ else
+ return -1;
+}
+
+EXPORT_SYMBOL(vpe1_sw_stop);
+
+uint32_t vpe1_get_load_addr (uint32_t flags)
+{
+ return vpe1_load_addr;
+}
+
+EXPORT_SYMBOL(vpe1_get_load_addr);
+
+uint32_t vpe1_get_max_mem (uint32_t flags)
+{
+ if (!vpe1_mem)
+ return P_SIZE;
+ else
+ return vpe1_mem;
+}
+
+EXPORT_SYMBOL(vpe1_get_max_mem);
+
+void* vpe1_get_cmdline_argument(void)
+{
+ return saved_command_line;
+}
+
+EXPORT_SYMBOL(vpe1_get_cmdline_argument);
+
+int32_t vpe1_set_boot_param(char *field, char *value, char flags)
+{
+ char *ptr, string[64];
+ int start_off, end_off;
+ if (!field)
+ return -1;
+ strcpy(string, field);
+ if (value) {
+ strcat(string, "=");
+ strcat(string, value);
+ strcat(command_line, " ");
+ strcat(command_line, string);
+ }
+ else {
+ ptr = strstr(command_line, string);
+ if (ptr) {
+ start_off = ptr - command_line;
+ ptr += strlen(string);
+ while ((*ptr != ' ') && (*ptr != '\0'))
+ ptr++;
+ end_off = ptr - command_line;
+ command_line[start_off] = '\0';
+ strcat (command_line, command_line+end_off);
+ }
+ }
+ return 0;
+}
+
+EXPORT_SYMBOL(vpe1_set_boot_param);
+
+int32_t vpe1_get_boot_param(char *field, char **value, char flags)
+{
+ char *ptr, string[64];
+ int i = 0;
+ if (!field)
+ return -1;
+ if ((ptr = strstr(command_line, field))) {
+ ptr += strlen(field) + 1; /* including = */
+ while ((*ptr != ' ') && (*ptr != '\0'))
+ string[i++] = *ptr++;
+ string[i] = '\0';
+ *value = kmalloc((strlen(string) + 1), GFP_KERNEL);
+ if (*value != NULL)
+ strcpy(*value, string);
+ }
+ else
+ *value = NULL;
+
+ return 0;
+}
+
+EXPORT_SYMBOL(vpe1_get_boot_param);
+
+extern void configure_tlb(void);
+#endif
static ssize_t store_kill(struct device *dev, struct device_attribute *attr,
const char *buf, size_t len)
@@ -1430,6 +1659,18 @@ static int __init vpe_module_init(void)
printk("VPE loader: not a MIPS MT capable processor\n");
return -ENODEV;
}
+#ifdef CONFIG_IFX_VPE_EXT
+#ifndef CONFIG_MIPS_MT_SMTC
+ configure_tlb();
+#endif
+#endif
+
+#ifndef CONFIG_MIPS_MT_SMTC
+ if (!vpelimit)
+ vpelimit = 1;
+ if (!tclimit)
+ tclimit = 1;
+#endif
if (vpelimit == 0) {
printk(KERN_WARNING "No VPEs reserved for AP/SP, not "
@@ -1474,10 +1715,12 @@ static int __init vpe_module_init(void)
mtflags = dmt();
vpflags = dvpe();
+ back_to_back_c0_hazard();
+
/* Put MVPE's into 'configuration state' */
set_c0_mvpcontrol(MVPCONTROL_VPC);
- /* dump_mtregs(); */
+ dump_mtregs();
val = read_c0_mvpconf0();
hw_tcs = (val & MVPCONF0_PTC) + 1;
@@ -1489,6 +1732,7 @@ static int __init vpe_module_init(void)
* reschedule send IPIs or similar we might hang.
*/
clear_c0_mvpcontrol(MVPCONTROL_VPC);
+ back_to_back_c0_hazard();
evpe(vpflags);
emt(mtflags);
local_irq_restore(flags);
@@ -1514,6 +1758,7 @@ static int __init vpe_module_init(void)
}
v->ntcs = hw_tcs - tclimit;
+ write_tc_c0_tcbind((read_tc_c0_tcbind() & ~TCBIND_CURVPE) | 1);
/* add the tc to the list of this vpe's tc's. */
list_add(&t->tc, &v->tc);
@@ -1582,6 +1827,7 @@ static int __init vpe_module_init(void)
out_reenable:
/* release config state */
clear_c0_mvpcontrol(MVPCONTROL_VPC);
+ back_to_back_c0_hazard();
evpe(vpflags);
emt(mtflags);

View File

@ -10,10 +10,8 @@ Subject: [PATCH 20/24] MIPS: lantiq: adds falcon VPE softdog
create mode 100644 arch/mips/include/asm/mach-lantiq/falcon/vpe.h
create mode 100644 arch/mips/lantiq/falcon/softdog_vpe.c
Index: linux-3.0.3/arch/mips/include/asm/mach-lantiq/falcon/vpe.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-3.0.3/arch/mips/include/asm/mach-lantiq/falcon/vpe.h 2011-10-05 13:26:22.732981532 +0200
--- /dev/null
+++ b/arch/mips/include/asm/mach-lantiq/falcon/vpe.h
@@ -0,0 +1,44 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
@ -59,10 +57,8 @@ Index: linux-3.0.3/arch/mips/include/asm/mach-lantiq/falcon/vpe.h
+int32_t vpe1_sw_wdog_register_reset_handler(VPE_SW_WDOG_RESET reset_fn);
+
+#endif
Index: linux-3.0.3/arch/mips/lantiq/falcon/softdog_vpe.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-3.0.3/arch/mips/lantiq/falcon/softdog_vpe.c 2011-10-05 13:26:22.736981533 +0200
--- /dev/null
+++ b/arch/mips/lantiq/falcon/softdog_vpe.c
@@ -0,0 +1,109 @@
+/*
+** =============================================================================
@ -173,10 +169,8 @@ Index: linux-3.0.3/arch/mips/lantiq/falcon/softdog_vpe.c
+MODULE_AUTHOR("LXDB");
+MODULE_DESCRIPTION("Software Watchdog For VPE1");
+MODULE_LICENSE("GPL");
Index: linux-3.0.3/arch/mips/lantiq/falcon/Makefile
===================================================================
--- linux-3.0.3.orig/arch/mips/lantiq/falcon/Makefile 2011-10-05 13:38:41.801013127 +0200
+++ linux-3.0.3/arch/mips/lantiq/falcon/Makefile 2011-10-05 13:38:47.341013363 +0200
--- a/arch/mips/lantiq/falcon/Makefile
+++ b/arch/mips/lantiq/falcon/Makefile
@@ -1,2 +1,2 @@
-obj-y := clk.o prom.o reset.o sysctrl.o devices.o gpio.o
+obj-y := clk.o prom.o reset.o sysctrl.o devices.o gpio.o softdog_vpe.o

View File

@ -9,11 +9,9 @@ Subject: [PATCH 21/24] MIPS: lantiq: adds cache split
arch/mips/mm/c-r4k.c | 172 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 260 insertions(+), 0 deletions(-)
Index: linux-3.0.3/arch/mips/Kconfig
===================================================================
--- linux-3.0.3.orig/arch/mips/Kconfig 2011-10-05 12:53:54.792898260 +0200
+++ linux-3.0.3/arch/mips/Kconfig 2011-10-05 12:53:54.852898263 +0200
@@ -1913,6 +1913,28 @@
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -1922,6 +1922,28 @@ config IFX_VPE_EXT
help
IFX included extensions in APRP
@ -42,11 +40,9 @@ Index: linux-3.0.3/arch/mips/Kconfig
config PERFCTRS
bool "34K Performance counters"
depends on MIPS_MT && PROC_FS
Index: linux-3.0.3/arch/mips/kernel/vpe.c
===================================================================
--- linux-3.0.3.orig/arch/mips/kernel/vpe.c 2011-10-05 12:53:54.800898262 +0200
+++ linux-3.0.3/arch/mips/kernel/vpe.c 2011-10-05 12:53:54.852898263 +0200
@@ -128,6 +128,13 @@
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -128,6 +128,13 @@ __setup("vpe1_wdog_timeout=", wdog_timeo
EXPORT_SYMBOL(vpe1_wdog_timeout);
#endif
@ -60,7 +56,7 @@ Index: linux-3.0.3/arch/mips/kernel/vpe.c
/* grab the likely amount of memory we will need. */
#ifdef CONFIG_MIPS_VPE_LOADER_TOM
#define P_SIZE (2 * 1024 * 1024)
@@ -866,6 +873,65 @@
@@ -866,6 +873,65 @@ static int vpe_run(struct vpe * v)
/* enable this VPE */
write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);
@ -126,11 +122,9 @@ Index: linux-3.0.3/arch/mips/kernel/vpe.c
/* clear out any left overs from a previous program */
write_vpe_c0_status(0);
write_vpe_c0_cause(0);
Index: linux-3.0.3/arch/mips/mm/c-r4k.c
===================================================================
--- linux-3.0.3.orig/arch/mips/mm/c-r4k.c 2011-08-17 19:57:16.000000000 +0200
+++ linux-3.0.3/arch/mips/mm/c-r4k.c 2011-10-05 12:53:54.852898263 +0200
@@ -1346,6 +1346,106 @@
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -1350,6 +1350,106 @@ static int __init setcoherentio(char *st
__setup("coherentio", setcoherentio);
#endif
@ -237,7 +231,7 @@ Index: linux-3.0.3/arch/mips/mm/c-r4k.c
void __cpuinit r4k_cache_init(void)
{
extern void build_clear_page(void);
@@ -1365,6 +1465,78 @@
@@ -1369,6 +1469,78 @@ void __cpuinit r4k_cache_init(void)
break;
}
@ -316,10 +310,8 @@ Index: linux-3.0.3/arch/mips/mm/c-r4k.c
probe_pcache();
setup_scache();
Index: linux-3.0.3/arch/mips/lantiq/setup.c
===================================================================
--- linux-3.0.3.orig/arch/mips/lantiq/setup.c 2011-10-05 13:20:49.808967301 +0200
+++ linux-3.0.3/arch/mips/lantiq/setup.c 2011-10-05 13:23:27.796974054 +0200
--- a/arch/mips/lantiq/setup.c
+++ b/arch/mips/lantiq/setup.c
@@ -18,10 +18,11 @@
#include "devices.h"
#include "prom.h"
@ -334,7 +326,7 @@ Index: linux-3.0.3/arch/mips/lantiq/setup.c
char **envp = (char **) KSEG1ADDR(fw_arg2);
ioport_resource.start = IOPORT_RESOURCE_START;
@@ -35,13 +36,13 @@
@@ -35,13 +36,13 @@ void __init plat_mem_setup(void)
char *e = (char *)KSEG1ADDR(*envp);
if (!strncmp(e, "memsize=", 8)) {
e += 8;

View File

@ -13,9 +13,6 @@ Subject: [PATCH 22/24] MIPS: lantiq: adds udp in-kernel redirect
create mode 100644 include/linux/udp_redirect.h
create mode 100644 net/ipv4/udp_redirect_symb.c
diff --git a/include/linux/udp_redirect.h b/include/linux/udp_redirect.h
new file mode 100644
index 0000000..de1e64f
--- /dev/null
+++ b/include/linux/udp_redirect.h
@@ -0,0 +1,57 @@
@ -76,8 +73,6 @@ index 0000000..de1e64f
+extern int udpredirect_getfrag(void *p, char * to, int offset,
+ int fraglen, int odd, struct sk_buff *skb);
+#endif
diff --git a/net/Kconfig b/net/Kconfig
index a073148..d13e3fa 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -72,6 +72,12 @@ config INET
@ -93,11 +88,9 @@ index a073148..d13e3fa 100644
if INET
source "net/ipv4/Kconfig"
source "net/ipv6/Kconfig"
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
index f2dc69c..6badd72 100644
--- a/net/ipv4/Makefile
+++ b/net/ipv4/Makefile
@@ -14,6 +14,9 @@ obj-y := route.o inetpeer.o protocol.o \
@@ -14,6 +14,9 @@ obj-y := route.o inetpeer.o protocol
inet_fragment.o ping.o
obj-$(CONFIG_SYSCTL) += sysctl_net_ipv4.o
@ -107,8 +100,6 @@ index f2dc69c..6badd72 100644
obj-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o
obj-$(CONFIG_IP_MROUTE) += ipmr.o
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 1b5a193..4d15cf6 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -108,6 +108,10 @@
@ -122,7 +113,7 @@ index 1b5a193..4d15cf6 100644
struct udp_table udp_table __read_mostly;
EXPORT_SYMBOL(udp_table);
@@ -803,7 +807,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
@@ -803,7 +807,7 @@ int udp_sendmsg(struct kiocb *iocb, stru
u8 tos;
int err, is_udplite = IS_UDPLITE(sk);
int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
@ -131,7 +122,7 @@ index 1b5a193..4d15cf6 100644
struct sk_buff *skb;
struct ip_options_data opt_copy;
@@ -820,7 +824,13 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
@@ -820,7 +824,13 @@ int udp_sendmsg(struct kiocb *iocb, stru
ipc.opt = NULL;
ipc.tx_flags = 0;
@ -146,7 +137,7 @@ index 1b5a193..4d15cf6 100644
fl4 = &inet->cork.fl.u.ip4;
if (up->pending) {
@@ -1621,6 +1631,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
@@ -1621,6 +1631,7 @@ int __udp4_lib_rcv(struct sk_buff *skb,
struct rtable *rt = skb_rtable(skb);
__be32 saddr, daddr;
struct net *net = dev_net(skb->dev);
@ -154,7 +145,7 @@ index 1b5a193..4d15cf6 100644
/*
* Validate the packet.
@@ -1653,7 +1664,16 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
@@ -1653,7 +1664,16 @@ int __udp4_lib_rcv(struct sk_buff *skb,
sk = __udp4_lib_lookup_skb(skb, uh->source, uh->dest, udptable);
if (sk != NULL) {
@ -181,9 +172,6 @@ index 1b5a193..4d15cf6 100644
/* ------------------------------------------------------------------------ */
#ifdef CONFIG_PROC_FS
diff --git a/net/ipv4/udp_redirect_symb.c b/net/ipv4/udp_redirect_symb.c
new file mode 100644
index 0000000..5617e86
--- /dev/null
+++ b/net/ipv4/udp_redirect_symb.c
@@ -0,0 +1,186 @@
@ -373,6 +361,3 @@ index 0000000..5617e86
+EXPORT_SYMBOL(udp_do_redirect_fn);
+EXPORT_SYMBOL(udpredirect_getfrag_fn);
+#endif /* CONFIG_IFX_UDP_REDIRECT* */
--
1.7.5.4

View File

@ -19,10 +19,8 @@ Subject: [PATCH 23/24] MIPS: lantiq: adds basic vr9 support
create mode 100644 arch/mips/lantiq/xway/mach-fritz.c
create mode 100644 arch/mips/lantiq/xway/prom-vr9.c
Index: linux-3.0.3/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
===================================================================
--- linux-3.0.3.orig/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h 2011-10-04 20:05:48.000000000 +0200
+++ linux-3.0.3/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h 2011-10-04 20:05:54.234312800 +0200
--- a/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
+++ b/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
@@ -21,6 +21,7 @@
#define SOC_ID_ARX188 0x16C
#define SOC_ID_ARX168 0x16D
@ -39,10 +37,8 @@ Index: linux-3.0.3/arch/mips/include/asm/mach-lantiq/xway/lantiq_soc.h
#define LTQ_ETOP_SIZE 0x40000
/* GBIT - gigabit switch */
Index: linux-3.0.3/arch/mips/lantiq/Kconfig
===================================================================
--- linux-3.0.3.orig/arch/mips/lantiq/Kconfig 2011-10-04 20:03:54.000000000 +0200
+++ linux-3.0.3/arch/mips/lantiq/Kconfig 2011-10-04 20:05:54.238312800 +0200
--- a/arch/mips/lantiq/Kconfig
+++ b/arch/mips/lantiq/Kconfig
@@ -1,5 +1,8 @@
if LANTIQ
@ -52,7 +48,7 @@ Index: linux-3.0.3/arch/mips/lantiq/Kconfig
config SOC_TYPE_XWAY
bool
default n
@@ -17,6 +20,12 @@
@@ -17,6 +20,12 @@ config SOC_XWAY
select SOC_TYPE_XWAY
select HW_HAS_PCI
@ -65,21 +61,17 @@ Index: linux-3.0.3/arch/mips/lantiq/Kconfig
config SOC_FALCON
bool "FALCON"
endchoice
Index: linux-3.0.3/arch/mips/lantiq/Platform
===================================================================
--- linux-3.0.3.orig/arch/mips/lantiq/Platform 2011-10-04 20:03:54.000000000 +0200
+++ linux-3.0.3/arch/mips/lantiq/Platform 2011-10-04 20:05:54.238312800 +0200
@@ -6,4 +6,5 @@
--- a/arch/mips/lantiq/Platform
+++ b/arch/mips/lantiq/Platform
@@ -6,4 +6,5 @@ platform-$(CONFIG_LANTIQ) += lantiq/
cflags-$(CONFIG_LANTIQ) += -I$(srctree)/arch/mips/include/asm/mach-lantiq
load-$(CONFIG_LANTIQ) = 0xffffffff80002000
cflags-$(CONFIG_SOC_TYPE_XWAY) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/xway
+cflags-$(CONFIG_SOC_TYPE_VR9) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/xway
cflags-$(CONFIG_SOC_FALCON) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/falcon
Index: linux-3.0.3/arch/mips/lantiq/machtypes.h
===================================================================
--- linux-3.0.3.orig/arch/mips/lantiq/machtypes.h 2011-10-04 20:03:54.000000000 +0200
+++ linux-3.0.3/arch/mips/lantiq/machtypes.h 2011-10-04 20:05:54.238312800 +0200
@@ -20,6 +20,9 @@
--- a/arch/mips/lantiq/machtypes.h
+++ b/arch/mips/lantiq/machtypes.h
@@ -20,6 +20,9 @@ enum lantiq_mach_type {
LANTIQ_MACH_EASY98000, /* Falcon Eval Board, NOR Flash */
LANTIQ_MACH_EASY98000SF, /* Falcon Eval Board, Serial Flash */
LANTIQ_MACH_EASY98000NAND, /* Falcon Eval Board, NAND Flash */
@ -89,11 +81,9 @@ Index: linux-3.0.3/arch/mips/lantiq/machtypes.h
};
#endif
Index: linux-3.0.3/arch/mips/lantiq/xway/Kconfig
===================================================================
--- linux-3.0.3.orig/arch/mips/lantiq/xway/Kconfig 2011-08-17 19:57:16.000000000 +0200
+++ linux-3.0.3/arch/mips/lantiq/xway/Kconfig 2011-10-04 20:05:54.238312800 +0200
@@ -21,3 +21,15 @@
--- a/arch/mips/lantiq/xway/Kconfig
+++ b/arch/mips/lantiq/xway/Kconfig
@@ -21,3 +21,15 @@ config LANTIQ_MACH_EASY50601
endmenu
endif
@ -109,11 +99,9 @@ Index: linux-3.0.3/arch/mips/lantiq/xway/Kconfig
+endmenu
+
+endif
Index: linux-3.0.3/arch/mips/lantiq/xway/Makefile
===================================================================
--- linux-3.0.3.orig/arch/mips/lantiq/xway/Makefile 2011-10-04 20:05:50.000000000 +0200
+++ linux-3.0.3/arch/mips/lantiq/xway/Makefile 2011-10-04 20:05:54.238312800 +0200
@@ -2,6 +2,8 @@
--- a/arch/mips/lantiq/xway/Makefile
+++ b/arch/mips/lantiq/xway/Makefile
@@ -2,6 +2,8 @@ obj-y := sysctrl.o reset.o gpio.o gpio_s
obj-$(CONFIG_SOC_XWAY) += clk-xway.o prom-xway.o
obj-$(CONFIG_SOC_AMAZON_SE) += clk-ase.o prom-ase.o
@ -122,10 +110,8 @@ Index: linux-3.0.3/arch/mips/lantiq/xway/Makefile
obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o
obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o
+obj-$(CONFIG_LANTIQ_MACH_FRITZ3370) += mach-fritz.o
Index: linux-3.0.3/arch/mips/lantiq/xway/clk-vr9.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-3.0.3/arch/mips/lantiq/xway/clk-vr9.c 2011-10-04 20:05:54.238312800 +0200
--- /dev/null
+++ b/arch/mips/lantiq/xway/clk-vr9.c
@@ -0,0 +1,78 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
@ -205,10 +191,8 @@ Index: linux-3.0.3/arch/mips/lantiq/xway/clk-vr9.c
+ return ltq_get_fpi_hz();
+}
+EXPORT_SYMBOL(ltq_get_fpi_bus_clock);
Index: linux-3.0.3/arch/mips/lantiq/xway/prom-vr9.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-3.0.3/arch/mips/lantiq/xway/prom-vr9.c 2011-10-04 20:05:54.238312800 +0200
--- /dev/null
+++ b/arch/mips/lantiq/xway/prom-vr9.c
@@ -0,0 +1,55 @@
+/*
+ * This program is free software; you can redistribute it and/or modify it
@ -265,11 +249,9 @@ Index: linux-3.0.3/arch/mips/lantiq/xway/prom-vr9.c
+ ltq_register_gpio();
+ ltq_register_wdt();
+}
Index: linux-3.0.3/arch/mips/pci/Makefile
===================================================================
--- linux-3.0.3.orig/arch/mips/pci/Makefile 2011-08-17 19:57:16.000000000 +0200
+++ linux-3.0.3/arch/mips/pci/Makefile 2011-10-04 20:05:54.238312800 +0200
@@ -41,7 +41,7 @@
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -41,7 +41,7 @@ obj-$(CONFIG_SIBYTE_SB1250) += fixup-sb1
obj-$(CONFIG_SIBYTE_BCM112X) += fixup-sb1250.o pci-sb1250.o
obj-$(CONFIG_SIBYTE_BCM1x80) += pci-bcm1480.o pci-bcm1480ht.o
obj-$(CONFIG_SNI_RM) += fixup-sni.o ops-sni.o

View File

@ -0,0 +1,36 @@
From 2dfa2b3e50c5ac49052233d15fa427a9b9136df8 Mon Sep 17 00:00:00 2001
From: John Crispin <blogic@openwrt.org>
Date: Thu, 27 Oct 2011 20:06:05 +0200
Subject: [PATCH 10/22] MIPS: lantiq: fixes STP based gpios
The STP engine has 3 groups of 8 pins. Only the first was activated by default.
Signed-off-by: Matti Laakso <malaakso@elisanet.fi>
Signed-off-by: John Crispin <blogic@openwrt.org>
---
arch/mips/lantiq/xway/gpio_stp.c | 7 +++++--
1 files changed, 5 insertions(+), 2 deletions(-)
--- a/arch/mips/lantiq/xway/gpio_stp.c
+++ b/arch/mips/lantiq/xway/gpio_stp.c
@@ -35,6 +35,8 @@
#define LTQ_STP_ADSL_SRC (3 << 24)
#define LTQ_STP_GROUP0 (1 << 0)
+#define LTQ_STP_GROUP1 (1 << 1)
+#define LTQ_STP_GROUP2 (1 << 2)
#define LTQ_STP_RISING 0
#define LTQ_STP_FALLING (1 << 26)
@@ -93,8 +95,9 @@ static int ltq_stp_hw_init(void)
/* rising or falling edge */
ltq_stp_w32_mask(LTQ_STP_EDGE_MASK, LTQ_STP_FALLING, LTQ_STP_CON0);
- /* per default stp 15-0 are set */
- ltq_stp_w32_mask(0, LTQ_STP_GROUP0, LTQ_STP_CON1);
+ /* enable all three led groups */
+ ltq_stp_w32_mask(0, LTQ_STP_GROUP0 | LTQ_STP_GROUP1 | LTQ_STP_GROUP2,
+ LTQ_STP_CON1);
/* stp are update periodically by the FPI bus */
ltq_stp_w32_mask(LTQ_STP_UPD_MASK, LTQ_STP_UPD_FPI, LTQ_STP_CON1);

Some files were not shown because too many files have changed in this diff Show More