M7350v1_en_gpl

This commit is contained in:
T
2024-09-09 08:52:07 +00:00
commit f9cc65cfda
65988 changed files with 26357421 additions and 0 deletions
+23
View File
@@ -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
+7
View File
@@ -0,0 +1,7 @@
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
obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o
obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o
+48
View File
@@ -0,0 +1,48 @@
/*
* 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 <linux/io.h>
#include <linux/export.h>
#include <linux/init.h>
#include <linux/clk.h>
#include <asm/time.h>
#include <asm/irq.h>
#include <asm/div64.h>
#include <lantiq_soc.h>
/* cgu registers */
#define LTQ_CGU_SYS 0x0010
unsigned int ltq_get_io_region_clock(void)
{
return CLOCK_133M;
}
EXPORT_SYMBOL(ltq_get_io_region_clock);
unsigned int ltq_get_fpi_bus_clock(int fpi)
{
return CLOCK_133M;
}
EXPORT_SYMBOL(ltq_get_fpi_bus_clock);
unsigned int ltq_get_cpu_hz(void)
{
if (ltq_cgu_r32(LTQ_CGU_SYS) & (1 << 5))
return CLOCK_266M;
else
return CLOCK_133M;
}
EXPORT_SYMBOL(ltq_get_cpu_hz);
unsigned int ltq_get_fpi_hz(void)
{
return CLOCK_133M;
}
EXPORT_SYMBOL(ltq_get_fpi_hz);
+223
View File
@@ -0,0 +1,223 @@
/*
* 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/io.h>
#include <linux/export.h>
#include <linux/init.h>
#include <linux/clk.h>
#include <asm/time.h>
#include <asm/irq.h>
#include <asm/div64.h>
#include <lantiq_soc.h>
static unsigned int ltq_ram_clocks[] = {
CLOCK_167M, CLOCK_133M, CLOCK_111M, CLOCK_83M };
#define DDR_HZ ltq_ram_clocks[ltq_cgu_r32(LTQ_CGU_SYS) & 0x3]
#define BASIC_FREQUENCY_1 35328000
#define BASIC_FREQUENCY_2 36000000
#define BASIS_REQUENCY_USB 12000000
#define GET_BITS(x, msb, lsb) \
(((x) & ((1 << ((msb) + 1)) - 1)) >> (lsb))
#define LTQ_CGU_PLL0_CFG 0x0004
#define LTQ_CGU_PLL1_CFG 0x0008
#define LTQ_CGU_PLL2_CFG 0x000C
#define LTQ_CGU_SYS 0x0010
#define LTQ_CGU_UPDATE 0x0014
#define LTQ_CGU_IF_CLK 0x0018
#define LTQ_CGU_OSC_CON 0x001C
#define LTQ_CGU_SMD 0x0020
#define LTQ_CGU_CT1SR 0x0028
#define LTQ_CGU_CT2SR 0x002C
#define LTQ_CGU_PCMCR 0x0030
#define LTQ_CGU_PCI_CR 0x0034
#define LTQ_CGU_PD_PC 0x0038
#define LTQ_CGU_FMR 0x003C
#define CGU_PLL0_PHASE_DIVIDER_ENABLE \
(ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 31))
#define CGU_PLL0_BYPASS \
(ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 30))
#define CGU_PLL0_CFG_DSMSEL \
(ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 28))
#define CGU_PLL0_CFG_FRAC_EN \
(ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & (1 << 27))
#define CGU_PLL1_SRC \
(ltq_cgu_r32(LTQ_CGU_PLL1_CFG) & (1 << 31))
#define CGU_PLL2_PHASE_DIVIDER_ENABLE \
(ltq_cgu_r32(LTQ_CGU_PLL2_CFG) & (1 << 20))
#define CGU_SYS_FPI_SEL (1 << 6)
#define CGU_SYS_DDR_SEL 0x3
#define CGU_PLL0_SRC (1 << 29)
#define CGU_PLL0_CFG_PLLK GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 26, 17)
#define CGU_PLL0_CFG_PLLN GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 12, 6)
#define CGU_PLL0_CFG_PLLM GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL0_CFG), 5, 2)
#define CGU_PLL2_SRC GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL2_CFG), 18, 17)
#define CGU_PLL2_CFG_INPUT_DIV GET_BITS(ltq_cgu_r32(LTQ_CGU_PLL2_CFG), 16, 13)
static unsigned int ltq_get_pll0_fdiv(void);
static inline unsigned int get_input_clock(int pll)
{
switch (pll) {
case 0:
if (ltq_cgu_r32(LTQ_CGU_PLL0_CFG) & CGU_PLL0_SRC)
return BASIS_REQUENCY_USB;
else if (CGU_PLL0_PHASE_DIVIDER_ENABLE)
return BASIC_FREQUENCY_1;
else
return BASIC_FREQUENCY_2;
case 1:
if (CGU_PLL1_SRC)
return BASIS_REQUENCY_USB;
else if (CGU_PLL0_PHASE_DIVIDER_ENABLE)
return BASIC_FREQUENCY_1;
else
return BASIC_FREQUENCY_2;
case 2:
switch (CGU_PLL2_SRC) {
case 0:
return ltq_get_pll0_fdiv();
case 1:
return CGU_PLL2_PHASE_DIVIDER_ENABLE ?
BASIC_FREQUENCY_1 :
BASIC_FREQUENCY_2;
case 2:
return BASIS_REQUENCY_USB;
}
default:
return 0;
}
}
static inline unsigned int cal_dsm(int pll, unsigned int num, unsigned int den)
{
u64 res, clock = get_input_clock(pll);
res = num * clock;
do_div(res, den);
return res;
}
static inline unsigned int mash_dsm(int pll, unsigned int M, unsigned int N,
unsigned int K)
{
unsigned int num = ((N + 1) << 10) + K;
unsigned int den = (M + 1) << 10;
return cal_dsm(pll, num, den);
}
static inline unsigned int ssff_dsm_1(int pll, unsigned int M, unsigned int N,
unsigned int K)
{
unsigned int num = ((N + 1) << 11) + K + 512;
unsigned int den = (M + 1) << 11;
return cal_dsm(pll, num, den);
}
static inline unsigned int ssff_dsm_2(int pll, unsigned int M, unsigned int N,
unsigned int K)
{
unsigned int num = K >= 512 ?
((N + 1) << 12) + K - 512 : ((N + 1) << 12) + K + 3584;
unsigned int den = (M + 1) << 12;
return cal_dsm(pll, num, den);
}
static inline unsigned int dsm(int pll, unsigned int M, unsigned int N,
unsigned int K, unsigned int dsmsel, unsigned int phase_div_en)
{
if (!dsmsel)
return mash_dsm(pll, M, N, K);
else if (!phase_div_en)
return mash_dsm(pll, M, N, K);
else
return ssff_dsm_2(pll, M, N, K);
}
static inline unsigned int ltq_get_pll0_fosc(void)
{
if (CGU_PLL0_BYPASS)
return get_input_clock(0);
else
return !CGU_PLL0_CFG_FRAC_EN
? dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN, 0,
CGU_PLL0_CFG_DSMSEL,
CGU_PLL0_PHASE_DIVIDER_ENABLE)
: dsm(0, CGU_PLL0_CFG_PLLM, CGU_PLL0_CFG_PLLN,
CGU_PLL0_CFG_PLLK, CGU_PLL0_CFG_DSMSEL,
CGU_PLL0_PHASE_DIVIDER_ENABLE);
}
static unsigned int ltq_get_pll0_fdiv(void)
{
unsigned int div = CGU_PLL2_CFG_INPUT_DIV + 1;
return (ltq_get_pll0_fosc() + (div >> 1)) / div;
}
unsigned int ltq_get_io_region_clock(void)
{
unsigned int ret = ltq_get_pll0_fosc();
switch (ltq_cgu_r32(LTQ_CGU_PLL2_CFG) & CGU_SYS_DDR_SEL) {
default:
case 0:
return (ret + 1) / 2;
case 1:
return (ret * 2 + 2) / 5;
case 2:
return (ret + 1) / 3;
case 3:
return (ret + 2) / 4;
}
}
EXPORT_SYMBOL(ltq_get_io_region_clock);
unsigned int ltq_get_fpi_bus_clock(int fpi)
{
unsigned int ret = ltq_get_io_region_clock();
if ((fpi == 2) && (ltq_cgu_r32(LTQ_CGU_SYS) & CGU_SYS_FPI_SEL))
ret >>= 1;
return ret;
}
EXPORT_SYMBOL(ltq_get_fpi_bus_clock);
unsigned int ltq_get_cpu_hz(void)
{
switch (ltq_cgu_r32(LTQ_CGU_SYS) & 0xc) {
case 0:
return CLOCK_333M;
case 4:
return DDR_HZ;
case 8:
return DDR_HZ << 1;
default:
return DDR_HZ >> 1;
}
}
EXPORT_SYMBOL(ltq_get_cpu_hz);
unsigned int ltq_get_fpi_hz(void)
{
unsigned int ddr_clock = DDR_HZ;
if (ltq_cgu_r32(LTQ_CGU_SYS) & 0x40)
return ddr_clock >> 1;
return ddr_clock;
}
EXPORT_SYMBOL(ltq_get_fpi_hz);
+119
View File
@@ -0,0 +1,119 @@
/*
* 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/export.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/time.h>
#include <linux/io.h>
#include <linux/gpio.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));
}
/* 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);
}
}
+20
View File
@@ -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) 2010 John Crispin <blogic@openwrt.org>
*/
#ifndef _LTQ_DEVICES_XWAY_H__
#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);
extern void ltq_register_ase_asc(void);
extern void ltq_register_etop(struct ltq_eth_data *eth);
#endif
+254
View File
@@ -0,0 +1,254 @@
/*
* 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 <linux/export.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");
if (request_mem_region(ltq_dma_resource.start,
resource_size(&ltq_dma_resource), "dma") < 0)
panic("Failed to request dma memory");
/* 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");
/* 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);
+52
View File
@@ -0,0 +1,52 @@
/*
* 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.
*
* EBU - the external bus unit attaches PCI, NOR and NAND
*
* Copyright (C) 2010 John Crispin <blogic@openwrt.org>
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/ioport.h>
#include <lantiq_soc.h>
/* all access to the ebu must be locked */
DEFINE_SPINLOCK(ebu_lock);
EXPORT_SYMBOL_GPL(ebu_lock);
static struct resource ltq_ebu_resource = {
.name = "ebu",
.start = LTQ_EBU_BASE_ADDR,
.end = LTQ_EBU_BASE_ADDR + LTQ_EBU_SIZE - 1,
.flags = IORESOURCE_MEM,
};
/* remapped base addr of the clock unit and external bus unit */
void __iomem *ltq_ebu_membase;
static int __init lantiq_ebu_init(void)
{
/* insert and request the memory region */
if (insert_resource(&iomem_resource, &ltq_ebu_resource) < 0)
panic("Failed to insert ebu memory");
if (request_mem_region(ltq_ebu_resource.start,
resource_size(&ltq_ebu_resource), "ebu") < 0)
panic("Failed to request ebu memory");
/* remap ebu register range */
ltq_ebu_membase = ioremap_nocache(ltq_ebu_resource.start,
resource_size(&ltq_ebu_resource));
if (!ltq_ebu_membase)
panic("Failed to remap ebu memory");
/* 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);
return 0;
}
postcore_initcall(lantiq_ebu_init);
+195
View File
@@ -0,0 +1,195 @@
/*
* 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/slab.h>
#include <linux/export.h>
#include <linux/platform_device.h>
#include <linux/gpio.h>
#include <linux/ioport.h>
#include <linux/io.h>
#include <lantiq_soc.h>
#define LTQ_GPIO_OUT 0x00
#define LTQ_GPIO_IN 0x04
#define LTQ_GPIO_DIR 0x08
#define LTQ_GPIO_ALTSEL0 0x0C
#define LTQ_GPIO_ALTSEL1 0x10
#define LTQ_GPIO_OD 0x14
#define PINS_PER_PORT 16
#define MAX_PORTS 3
#define ltq_gpio_getbit(m, r, p) (!!(ltq_r32(m + r) & (1 << p)))
#define ltq_gpio_setbit(m, r, p) ltq_w32_mask(0, (1 << p), m + r)
#define ltq_gpio_clearbit(m, r, p) ltq_w32_mask((1 << p), 0, m + r)
struct ltq_gpio {
void __iomem *membase;
struct gpio_chip chip;
};
static struct ltq_gpio ltq_gpio_port[MAX_PORTS];
int gpio_to_irq(unsigned int gpio)
{
return -EINVAL;
}
EXPORT_SYMBOL(gpio_to_irq);
int irq_to_gpio(unsigned int gpio)
{
return -EINVAL;
}
EXPORT_SYMBOL(irq_to_gpio);
int ltq_gpio_request(unsigned int pin, unsigned int alt0,
unsigned int alt1, unsigned int dir, const char *name)
{
int id = 0;
if (pin >= (MAX_PORTS * PINS_PER_PORT))
return -EINVAL;
if (gpio_request(pin, name)) {
pr_err("failed to setup lantiq gpio: %s\n", name);
return -EBUSY;
}
if (dir)
gpio_direction_output(pin, 1);
else
gpio_direction_input(pin);
while (pin >= PINS_PER_PORT) {
pin -= PINS_PER_PORT;
id++;
}
if (alt0)
ltq_gpio_setbit(ltq_gpio_port[id].membase,
LTQ_GPIO_ALTSEL0, pin);
else
ltq_gpio_clearbit(ltq_gpio_port[id].membase,
LTQ_GPIO_ALTSEL0, pin);
if (alt1)
ltq_gpio_setbit(ltq_gpio_port[id].membase,
LTQ_GPIO_ALTSEL1, pin);
else
ltq_gpio_clearbit(ltq_gpio_port[id].membase,
LTQ_GPIO_ALTSEL1, pin);
return 0;
}
EXPORT_SYMBOL(ltq_gpio_request);
static void ltq_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
{
struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
if (value)
ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_OUT, offset);
else
ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_OUT, offset);
}
static int ltq_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
return ltq_gpio_getbit(ltq_gpio->membase, LTQ_GPIO_IN, offset);
}
static int ltq_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
{
struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_OD, offset);
ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_DIR, offset);
return 0;
}
static int ltq_gpio_direction_output(struct gpio_chip *chip,
unsigned int offset, int value)
{
struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_OD, offset);
ltq_gpio_setbit(ltq_gpio->membase, LTQ_GPIO_DIR, offset);
ltq_gpio_set(chip, offset, value);
return 0;
}
static int ltq_gpio_req(struct gpio_chip *chip, unsigned offset)
{
struct ltq_gpio *ltq_gpio = container_of(chip, struct ltq_gpio, chip);
ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_ALTSEL0, offset);
ltq_gpio_clearbit(ltq_gpio->membase, LTQ_GPIO_ALTSEL1, offset);
return 0;
}
static int ltq_gpio_probe(struct platform_device *pdev)
{
struct resource *res;
if (pdev->id >= MAX_PORTS) {
dev_err(&pdev->dev, "invalid gpio port %d\n",
pdev->id);
return -EINVAL;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res) {
dev_err(&pdev->dev, "failed to get memory for gpio port %d\n",
pdev->id);
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 for gpio port %d\n",
pdev->id);
return -EBUSY;
}
ltq_gpio_port[pdev->id].membase = devm_ioremap_nocache(&pdev->dev,
res->start, resource_size(res));
if (!ltq_gpio_port[pdev->id].membase) {
dev_err(&pdev->dev, "failed to remap memory for gpio port %d\n",
pdev->id);
return -ENOMEM;
}
ltq_gpio_port[pdev->id].chip.label = "ltq_gpio";
ltq_gpio_port[pdev->id].chip.direction_input = ltq_gpio_direction_input;
ltq_gpio_port[pdev->id].chip.direction_output =
ltq_gpio_direction_output;
ltq_gpio_port[pdev->id].chip.get = ltq_gpio_get;
ltq_gpio_port[pdev->id].chip.set = ltq_gpio_set;
ltq_gpio_port[pdev->id].chip.request = ltq_gpio_req;
ltq_gpio_port[pdev->id].chip.base = PINS_PER_PORT * pdev->id;
ltq_gpio_port[pdev->id].chip.ngpio = PINS_PER_PORT;
platform_set_drvdata(pdev, &ltq_gpio_port[pdev->id]);
return gpiochip_add(&ltq_gpio_port[pdev->id].chip);
}
static struct platform_driver
ltq_gpio_driver = {
.probe = ltq_gpio_probe,
.driver = {
.name = "ltq_gpio",
.owner = THIS_MODULE,
},
};
int __init ltq_gpio_init(void)
{
int ret = platform_driver_register(&ltq_gpio_driver);
if (ret)
pr_info("ltq_gpio : Error registering platfom driver!");
return ret;
}
postcore_initcall(ltq_gpio_init);
+126
View File
@@ -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/export.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);
+157
View File
@@ -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/export.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);
@@ -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);
@@ -0,0 +1,74 @@
/*
* 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 <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 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,
"EASY50712",
"EASY50712 Eval Board",
easy50712_init);
+69
View File
@@ -0,0 +1,69 @@
/*
* 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/ioport.h>
#include <lantiq_soc.h>
/* PMU - the power management unit allows us to turn part of the core
* on and off
*/
/* the enable / disable registers */
#define LTQ_PMU_PWDCR 0x1C
#define LTQ_PMU_PWDSR 0x20
#define ltq_pmu_w32(x, y) ltq_w32((x), ltq_pmu_membase + (y))
#define ltq_pmu_r32(x) ltq_r32(ltq_pmu_membase + (x))
static struct resource ltq_pmu_resource = {
.name = "pmu",
.start = LTQ_PMU_BASE_ADDR,
.end = LTQ_PMU_BASE_ADDR + LTQ_PMU_SIZE - 1,
.flags = IORESOURCE_MEM,
};
static void __iomem *ltq_pmu_membase;
void ltq_pmu_enable(unsigned int module)
{
int err = 1000000;
ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) & ~module, LTQ_PMU_PWDCR);
do {} while (--err && (ltq_pmu_r32(LTQ_PMU_PWDSR) & module));
if (!err)
panic("activating PMU module failed!");
}
EXPORT_SYMBOL(ltq_pmu_enable);
void ltq_pmu_disable(unsigned int module)
{
ltq_pmu_w32(ltq_pmu_r32(LTQ_PMU_PWDCR) | module, LTQ_PMU_PWDCR);
}
EXPORT_SYMBOL(ltq_pmu_disable);
int __init ltq_pmu_init(void)
{
if (insert_resource(&iomem_resource, &ltq_pmu_resource) < 0)
panic("Failed to insert pmu memory");
if (request_mem_region(ltq_pmu_resource.start,
resource_size(&ltq_pmu_resource), "pmu") < 0)
panic("Failed to request pmu memory");
ltq_pmu_membase = ioremap_nocache(ltq_pmu_resource.start,
resource_size(&ltq_pmu_resource));
if (!ltq_pmu_membase)
panic("Failed to remap pmu memory");
return 0;
}
core_initcall(ltq_pmu_init);
+39
View File
@@ -0,0 +1,39 @@
/*
* 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/export.h>
#include <linux/clk.h>
#include <asm/bootinfo.h>
#include <asm/time.h>
#include <lantiq_soc.h>
#include "../prom.h"
#define SOC_AMAZON_SE "Amazon_SE"
#define PART_SHIFT 12
#define PART_MASK 0x0FFFFFFF
#define REV_SHIFT 28
#define REV_MASK 0xF0000000
void __init ltq_soc_detect(struct ltq_soc_info *i)
{
i->partnum = (ltq_r32(LTQ_MPS_CHIPID) & PART_MASK) >> PART_SHIFT;
i->rev = (ltq_r32(LTQ_MPS_CHIPID) & REV_MASK) >> REV_SHIFT;
switch (i->partnum) {
case SOC_ID_AMAZON_SE:
i->name = SOC_AMAZON_SE;
i->type = SOC_TYPE_AMAZON_SE;
break;
default:
unreachable();
break;
}
}
+54
View File
@@ -0,0 +1,54 @@
/*
* 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/export.h>
#include <linux/clk.h>
#include <asm/bootinfo.h>
#include <asm/time.h>
#include <lantiq_soc.h>
#include "../prom.h"
#define SOC_DANUBE "Danube"
#define SOC_TWINPASS "Twinpass"
#define SOC_AR9 "AR9"
#define PART_SHIFT 12
#define PART_MASK 0x0FFFFFFF
#define REV_SHIFT 28
#define REV_MASK 0xF0000000
void __init ltq_soc_detect(struct ltq_soc_info *i)
{
i->partnum = (ltq_r32(LTQ_MPS_CHIPID) & PART_MASK) >> PART_SHIFT;
i->rev = (ltq_r32(LTQ_MPS_CHIPID) & REV_MASK) >> REV_SHIFT;
switch (i->partnum) {
case SOC_ID_DANUBE1:
case SOC_ID_DANUBE2:
i->name = SOC_DANUBE;
i->type = SOC_TYPE_DANUBE;
break;
case SOC_ID_TWINPASS:
i->name = SOC_TWINPASS;
i->type = SOC_TYPE_DANUBE;
break;
case SOC_ID_ARX188:
case SOC_ID_ARX168:
case SOC_ID_ARX182:
i->name = SOC_AR9;
i->type = SOC_TYPE_AR9;
break;
default:
unreachable();
break;
}
}
+91
View File
@@ -0,0 +1,91 @@
/*
* 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/io.h>
#include <linux/ioport.h>
#include <linux/pm.h>
#include <linux/export.h>
#include <asm/reboot.h>
#include <lantiq_soc.h>
#define ltq_rcu_w32(x, y) ltq_w32((x), ltq_rcu_membase + (y))
#define ltq_rcu_r32(x) ltq_r32(ltq_rcu_membase + (x))
/* register definitions */
#define LTQ_RCU_RST 0x0010
#define LTQ_RCU_RST_ALL 0x40000000
#define LTQ_RCU_RST_STAT 0x0014
#define LTQ_RCU_STAT_SHIFT 26
static struct resource ltq_rcu_resource = {
.name = "rcu",
.start = LTQ_RCU_BASE_ADDR,
.end = LTQ_RCU_BASE_ADDR + LTQ_RCU_SIZE - 1,
.flags = IORESOURCE_MEM,
};
/* remapped base addr of the reset control unit */
static void __iomem *ltq_rcu_membase;
/* This function is used by the watchdog driver */
int ltq_reset_cause(void)
{
u32 val = ltq_rcu_r32(LTQ_RCU_RST_STAT);
return val >> LTQ_RCU_STAT_SHIFT;
}
EXPORT_SYMBOL_GPL(ltq_reset_cause);
static void ltq_machine_restart(char *command)
{
pr_notice("System restart\n");
local_irq_disable();
ltq_rcu_w32(ltq_rcu_r32(LTQ_RCU_RST) | LTQ_RCU_RST_ALL, LTQ_RCU_RST);
unreachable();
}
static void ltq_machine_halt(void)
{
pr_notice("System halted.\n");
local_irq_disable();
unreachable();
}
static void ltq_machine_power_off(void)
{
pr_notice("Please turn off the power now.\n");
local_irq_disable();
unreachable();
}
static int __init mips_reboot_setup(void)
{
/* insert and request the memory region */
if (insert_resource(&iomem_resource, &ltq_rcu_resource) < 0)
panic("Failed to insert rcu memory");
if (request_mem_region(ltq_rcu_resource.start,
resource_size(&ltq_rcu_resource), "rcu") < 0)
panic("Failed to request rcu memory");
/* remap rcu register range */
ltq_rcu_membase = ioremap_nocache(ltq_rcu_resource.start,
resource_size(&ltq_rcu_resource));
if (!ltq_rcu_membase)
panic("Failed to remap rcu memory");
_machine_restart = ltq_machine_restart;
_machine_halt = ltq_machine_halt;
pm_power_off = ltq_machine_power_off;
return 0;
}
arch_initcall(mips_reboot_setup);
+19
View File
@@ -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();
}
+20
View File
@@ -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();
}