* backport 2.6.8 patches to .39 / .32.33
* remove lqtapi * bump tapi/dsl to .39 * migrate to new ltq_ style api * add amazon_se support SVN-Revision: 27026
This commit is contained in:
parent
c7cdee0230
commit
6608f419d1
165 changed files with 54110 additions and 18452 deletions
|
@ -1,73 +0,0 @@
|
|||
#
|
||||
# Copyright (C) 2006-2010 OpenWrt.org
|
||||
#
|
||||
# This is free software, licensed under the GNU General Public License v2.
|
||||
# See /LICENSE for more information.
|
||||
#
|
||||
|
||||
include $(TOPDIR)/rules.mk
|
||||
include $(INCLUDE_DIR)/kernel.mk
|
||||
|
||||
PKG_NAME:=lqtapi
|
||||
PKG_VERSION:=1
|
||||
PKG_RELEASE:=1
|
||||
|
||||
FW_SOURCE:=danube_firmware.bin
|
||||
FW_URL:=http://www.arcor.de/hilfe/files/pdf/
|
||||
FW_FILE=arcor_A800_452CPW_FW_1.02.206(20081201).bin
|
||||
FW_MD5SUM:=19d9af4e369287a0f0abaed415cdac10
|
||||
|
||||
include $(INCLUDE_DIR)/package.mk
|
||||
|
||||
define Download/firmware
|
||||
FILE:=$(FW_FILE)
|
||||
URL:=$(FW_URL)
|
||||
MD5SUM:=$(FW_MD5SUM)
|
||||
endef
|
||||
$(eval $(call Download,firmware))
|
||||
|
||||
define KernelPackage/lqtapi
|
||||
SUBMENU:=Voice over IP
|
||||
TITLE:=Tapi drivers for Lantiq SoC
|
||||
DEPENDS:=@TARGET_lantiq_xway @BROKEN
|
||||
FILES:=$(PKG_BUILD_DIR)/tapi/tapi.ko \
|
||||
$(PKG_BUILD_DIR)/mps/mps.ko \
|
||||
$(PKG_BUILD_DIR)/mps/vmmc.ko
|
||||
AUTOLOAD:=$(call AutoLoad,80,tapi) \
|
||||
$(call AutoLoad,81,mps)
|
||||
endef
|
||||
|
||||
define Package/lqtapi-firmware-danube
|
||||
SECTION:=sys
|
||||
CATEGORY:=Kernel modules
|
||||
SUBMENU:=Voice over IP
|
||||
TITLE:=Danube firmware
|
||||
DEPENDS:=+kmod-lqtapi
|
||||
endef
|
||||
|
||||
include $(INCLUDE_DIR)/kernel-defaults.mk
|
||||
|
||||
define KernelPackage/lqtapi/description
|
||||
FOSS drivers for Lantiq SoC voip core
|
||||
endef
|
||||
|
||||
define Build/Prepare
|
||||
mkdir -p $(PKG_BUILD_DIR)
|
||||
$(CP) src/* $(PKG_BUILD_DIR)/
|
||||
endef
|
||||
|
||||
define Build/Compile
|
||||
$(MAKE) $(KERNEL_MAKEOPTS) \
|
||||
SUBDIRS="$(PKG_BUILD_DIR)" \
|
||||
EXTRA_CFLAGS=-I$(PKG_BUILD_DIR)/include/ \
|
||||
modules
|
||||
endef
|
||||
|
||||
define Package/lqtapi-firmware-danube/install
|
||||
$(TOPDIR)/target/linux/$(BOARD)/extract.sh $(DL_DIR) '$(FW_FILE)'
|
||||
$(INSTALL_DIR) $(1)/lib/firmware/
|
||||
$(INSTALL_DATA) $(DL_DIR)/voip.bin $(1)/lib/firmware/$(FW_SOURCE)
|
||||
endef
|
||||
|
||||
$(eval $(call KernelPackage,lqtapi))
|
||||
$(eval $(call BuildPackage,lqtapi-firmware-danube))
|
|
@ -1 +0,0 @@
|
|||
obj-m = tapi/ mps/
|
|
@ -1,37 +0,0 @@
|
|||
#ifndef __LINUX_TAPI_TAPI_EVENT_H__
|
||||
#define __LINUX_TAPI_TAPI_EVENT_H__
|
||||
|
||||
|
||||
struct tapi_device;
|
||||
struct tapi_port;
|
||||
|
||||
struct tapi_hook_event {
|
||||
bool on;
|
||||
};
|
||||
|
||||
struct tapi_dtmf_event {
|
||||
unsigned char code;
|
||||
};
|
||||
|
||||
enum tapi_event_type {
|
||||
TAPI_EVENT_TYPE_HOOK,
|
||||
TAPI_EVENT_TYPE_DTMF,
|
||||
};
|
||||
|
||||
struct tapi_event {
|
||||
struct timeval time;
|
||||
enum tapi_event_type type;
|
||||
unsigned int port;
|
||||
union {
|
||||
struct tapi_hook_event hook;
|
||||
struct tapi_dtmf_event dtmf;
|
||||
};
|
||||
};
|
||||
|
||||
void tapi_report_event(struct tapi_device *tdev, struct tapi_event *event);
|
||||
void tapi_report_hook_event(struct tapi_device *tdev, struct tapi_port *port,
|
||||
bool on);
|
||||
void tapi_report_dtmf_event(struct tapi_device *tdev, struct tapi_port *port,
|
||||
unsigned char code);
|
||||
|
||||
#endif
|
|
@ -1,20 +0,0 @@
|
|||
|
||||
#include <linux/ioctl.h>
|
||||
|
||||
#define TAPI_MAGIC 't'
|
||||
#define TAPI_IOCTL(x) _IO(TAPI_MAGIC, (x))
|
||||
|
||||
#define TAPI_CONTROL_IOCTL_LINK_ALLOC TAPI_IOCTL(0)
|
||||
#define TAPI_CONTROL_IOCTL_LINK_FREE TAPI_IOCTL(1)
|
||||
#define TAPI_CONTROL_IOCTL_LINK_ENABLE TAPI_IOCTL(2)
|
||||
#define TAPI_CONTROL_IOCTL_LINK_DISABLE TAPI_IOCTL(3)
|
||||
|
||||
#define TAPI_CONTROL_IOCTL_SYNC TAPI_IOCTL(4)
|
||||
|
||||
#define TAPI_PORT_IOCTL_GET_ENDPOINT TAPI_IOCTL(5)
|
||||
#define TAPI_PORT_IOCTL_SET_RING TAPI_IOCTL(6)
|
||||
|
||||
#define TAPI_STREAM_IOCTL_GET_ENDPOINT TAPI_IOCTL(7)
|
||||
#define TAPI_STREAM_IOCTL_CONFIGURE TAPI_IOCTL(8)
|
||||
#define TAPI_STREAM_IOCTL_START TAPI_IOCTL(9)
|
||||
#define TAPI_STREAM_IOCTL_STOP TAPI_IOCTL(10)
|
|
@ -1,231 +0,0 @@
|
|||
#ifndef __LINUX_TAPI_H__
|
||||
#define __LINUX_TAPI_H__
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include <linux/input.h>
|
||||
|
||||
#include <asm/atomic.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
#include <linux/cdev.h>
|
||||
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/wait.h>
|
||||
|
||||
#include <linux/tapi/tapi-event.h>
|
||||
|
||||
struct tapi_device;
|
||||
|
||||
struct tapi_char_device {
|
||||
struct tapi_device *tdev;
|
||||
struct device dev;
|
||||
struct cdev cdev;
|
||||
};
|
||||
|
||||
static inline struct tapi_char_device *cdev_to_tapi_char_device(struct cdev *cdev)
|
||||
{
|
||||
return container_of(cdev, struct tapi_char_device, cdev);
|
||||
}
|
||||
|
||||
int tapi_char_device_register(struct tapi_device *tdev,
|
||||
struct tapi_char_device *tchrdev, const struct file_operations *fops);
|
||||
|
||||
|
||||
struct tapi_endpoint {
|
||||
unsigned int id;
|
||||
void *data;
|
||||
};
|
||||
|
||||
static inline void tapi_endpoint_set_data(struct tapi_endpoint *ep, void *data)
|
||||
{
|
||||
ep->data = data;
|
||||
}
|
||||
|
||||
static inline void *tapi_endpoint_get_data(struct tapi_endpoint *ep)
|
||||
{
|
||||
return ep->data;
|
||||
}
|
||||
|
||||
struct tapi_port {
|
||||
unsigned int id;
|
||||
struct tapi_endpoint ep;
|
||||
struct input_dev *input;
|
||||
struct tapi_char_device chrdev;
|
||||
};
|
||||
|
||||
struct tapi_stream {
|
||||
unsigned int id;
|
||||
struct list_head head;
|
||||
struct tapi_endpoint ep;
|
||||
|
||||
struct sk_buff_head recv_queue;
|
||||
wait_queue_head_t recv_wait;
|
||||
struct sk_buff_head send_queue;
|
||||
};
|
||||
|
||||
struct tapi_link {
|
||||
unsigned int id;
|
||||
struct list_head head;
|
||||
};
|
||||
|
||||
enum tapi_codec {
|
||||
TAPI_CODEC_L16,
|
||||
};
|
||||
|
||||
struct tapi_stream_config {
|
||||
enum tapi_codec codec;
|
||||
unsigned int buffer_size;
|
||||
};
|
||||
|
||||
struct tapi_ops {
|
||||
int (*send_dtmf_events)(struct tapi_device *, struct tapi_port *port,
|
||||
struct tapi_dtmf_event *, size_t num_events, unsigned int dealy);
|
||||
int (*send_dtmf_event)(struct tapi_device *, struct tapi_port *port,
|
||||
struct tapi_dtmf_event *);
|
||||
int (*ring)(struct tapi_device *, struct tapi_port *port, bool ring);
|
||||
|
||||
struct tapi_stream *(*stream_alloc)(struct tapi_device *);
|
||||
void (*stream_free)(struct tapi_device *, struct tapi_stream *);
|
||||
int (*stream_configure)(struct tapi_device *, struct tapi_stream *,
|
||||
struct tapi_stream_config *);
|
||||
int (*stream_start)(struct tapi_device *, struct tapi_stream *);
|
||||
int (*stream_stop)(struct tapi_device *, struct tapi_stream *);
|
||||
int (*stream_send)(struct tapi_device *, struct tapi_stream *,
|
||||
struct sk_buff *);
|
||||
|
||||
struct tapi_link *(*link_alloc)(struct tapi_device *,
|
||||
struct tapi_endpoint *ep1, struct tapi_endpoint *ep2);
|
||||
void (*link_free)(struct tapi_device *, struct tapi_link *);
|
||||
int (*link_enable)(struct tapi_device *, struct tapi_link *);
|
||||
int (*link_disable)(struct tapi_device *, struct tapi_link *);
|
||||
|
||||
int (*sync)(struct tapi_device *);
|
||||
};
|
||||
|
||||
int tapi_stream_recv(struct tapi_device *, struct tapi_stream *, struct sk_buff *);
|
||||
|
||||
struct tapi_device {
|
||||
unsigned int id;
|
||||
|
||||
const struct tapi_ops *ops;
|
||||
unsigned int num_ports;
|
||||
|
||||
struct device dev;
|
||||
|
||||
struct mutex lock;
|
||||
|
||||
struct tapi_port *ports;
|
||||
struct list_head streams;
|
||||
struct list_head links;
|
||||
atomic_t stream_id;
|
||||
atomic_t link_id;
|
||||
|
||||
struct tapi_char_device stream_dev;
|
||||
struct tapi_char_device control_dev;
|
||||
};
|
||||
|
||||
static inline struct tapi_device *dev_to_tapi(struct device *dev)
|
||||
{
|
||||
return container_of(dev, struct tapi_device, dev);
|
||||
}
|
||||
|
||||
static inline struct tapi_stream *tapi_stream_from_id(struct tapi_device *tdev,
|
||||
unsigned int id)
|
||||
{
|
||||
struct tapi_stream *stream;
|
||||
|
||||
mutex_lock(&tdev->lock);
|
||||
|
||||
list_for_each_entry(stream, &tdev->streams, head) {
|
||||
if (stream->id == id)
|
||||
goto out;
|
||||
}
|
||||
stream = NULL;
|
||||
|
||||
out:
|
||||
mutex_unlock(&tdev->lock);
|
||||
return stream;
|
||||
}
|
||||
|
||||
struct tapi_link *tapi_link_alloc(struct tapi_device *, struct tapi_endpoint *,
|
||||
struct tapi_endpoint *);
|
||||
void tapi_link_free(struct tapi_device *, struct tapi_link *);
|
||||
|
||||
struct tapi_stream *tapi_stream_alloc(struct tapi_device *tdev);
|
||||
void tapi_stream_free(struct tapi_device *tdev, struct tapi_stream *stream);
|
||||
|
||||
static inline int tapi_sync(struct tapi_device *tdev)
|
||||
{
|
||||
if (!tdev->ops || !tdev->ops->sync)
|
||||
return 0;
|
||||
|
||||
return tdev->ops->sync(tdev);
|
||||
}
|
||||
|
||||
static inline int tapi_link_enable(struct tapi_device *tdev,
|
||||
struct tapi_link *link)
|
||||
{
|
||||
if (!tdev->ops || !tdev->ops->link_enable)
|
||||
return 0;
|
||||
|
||||
return tdev->ops->link_enable(tdev, link);
|
||||
}
|
||||
|
||||
static inline int tapi_link_disable(struct tapi_device *tdev,
|
||||
struct tapi_link *link)
|
||||
{
|
||||
if (!tdev->ops || !tdev->ops->link_disable)
|
||||
return 0;
|
||||
|
||||
return tdev->ops->link_disable(tdev, link);
|
||||
}
|
||||
|
||||
static inline int tapi_port_send_dtmf(struct tapi_device *tdev,
|
||||
struct tapi_port *port, struct tapi_dtmf_event *dtmf)
|
||||
{
|
||||
if (!tdev->ops || !tdev->ops->send_dtmf_event)
|
||||
return -ENOSYS;
|
||||
|
||||
return tdev->ops->send_dtmf_event(tdev, port, dtmf);
|
||||
}
|
||||
|
||||
static inline int tapi_port_set_ring(struct tapi_device *tdev,
|
||||
struct tapi_port *port, bool ring)
|
||||
{
|
||||
if (!tdev->ops || !tdev->ops->ring)
|
||||
return -ENOSYS;
|
||||
|
||||
return tdev->ops->ring(tdev, port, ring);
|
||||
}
|
||||
|
||||
static inline int tapi_stream_start(struct tapi_device *tdev,
|
||||
struct tapi_stream *stream)
|
||||
{
|
||||
if (!tdev->ops || !tdev->ops->stream_start)
|
||||
return -ENOSYS;
|
||||
|
||||
return tdev->ops->stream_start(tdev, stream);
|
||||
}
|
||||
|
||||
static inline int tapi_stream_stop(struct tapi_device *tdev,
|
||||
struct tapi_stream *stream)
|
||||
{
|
||||
if (!tdev->ops || !tdev->ops->stream_stop)
|
||||
return -ENOSYS;
|
||||
|
||||
return tdev->ops->stream_stop(tdev, stream);
|
||||
}
|
||||
|
||||
int tapi_device_register(struct tapi_device *tdev, const char *name,
|
||||
struct device *parent);
|
||||
void tapi_device_unregister(struct tapi_device *tdev);
|
||||
|
||||
struct tapi_sysfs_port;
|
||||
|
||||
struct tapi_sysfs_port *tapi_port_alloc(struct tapi_device *tdev, unsigned int id);
|
||||
void tapi_port_delete(struct tapi_sysfs_port *);
|
||||
|
||||
#endif
|
|
@ -1,8 +0,0 @@
|
|||
|
||||
|
||||
mps-objs := mps-core.o mps-irq.o mps-fifo.o
|
||||
obj-m += mps.o
|
||||
|
||||
vmmc-objs := vmmc-core.o vmmc-alm.o vmmc-module.o vmmc-link.o vmmc-port.o \
|
||||
vmmc-signal.o vmmc-stream.o vmmc-coder.o
|
||||
obj-m += vmmc.o
|
|
@ -1,238 +0,0 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <ifxmips.h>
|
||||
#include <ifxmips_cgu.h>
|
||||
|
||||
#include <ifxmips_prom.h>
|
||||
#include <ifxmips_irq.h>
|
||||
|
||||
#include "mps.h"
|
||||
|
||||
extern int mps_irq_init(struct mps *mps);
|
||||
extern void mps_irq_exit(struct mps *mps);
|
||||
|
||||
#define MPS_CPU0_BOOT_RVEC 0x1c0
|
||||
#define MPS_CPU0_BOOT_NVEC 0x1c4
|
||||
#define MPS_CPU0_BOOT_EVEC 0x1c8
|
||||
#define MPS_CPU0_CP0_STATUS 0x1cc
|
||||
#define MPS_CPU0_CP0_EEPC 0x1d0
|
||||
#define MPS_CPU0_CP0_EPC 0x1d4
|
||||
#define MPS_CPU0_BOOT_SIZE 0x1d8
|
||||
#define MPS_CPU0_CFG_STAT 0x1dc
|
||||
#define MPS_CPU1_BOOT_RVEC 0x1e0
|
||||
#define MPS_CPU1_BOOT_NVEC 0x1e4
|
||||
#define MPS_CPU1_BOOT_EVEC 0x1e8
|
||||
#define MPS_CPU1_CP0_STATUS 0x1ec
|
||||
#define MPS_CPU1_CP0_EEPC 0x1f0
|
||||
#define MPS_CPU1_CP0_EPC 0x1f4
|
||||
#define MPS_CPU1_BOOT_SIZE 0x1f8
|
||||
#define MPS_CPU1_CFG_STAT 0x1fc
|
||||
|
||||
static void mps_reset(void)
|
||||
{
|
||||
ifxmips_w32(ifxmips_r32(IFXMIPS_RCU_RST) | IFXMIPS_RCU_RST_CPU1,
|
||||
IFXMIPS_RCU_RST);
|
||||
smp_wmb();
|
||||
}
|
||||
|
||||
static void mps_release(void)
|
||||
{
|
||||
uint32_t val;
|
||||
val = ifxmips_r32(IFXMIPS_RCU_RST);
|
||||
val |= 0x20000000;
|
||||
val &= ~IFXMIPS_RCU_RST_CPU1;
|
||||
ifxmips_w32(val, IFXMIPS_RCU_RST);
|
||||
smp_wmb();
|
||||
}
|
||||
|
||||
void mps_load_firmware(struct mps *mps, const void *data, size_t size,
|
||||
enum mps_boot_config config)
|
||||
{
|
||||
uint32_t cfg = 0;
|
||||
uint32_t fw_size = size;
|
||||
|
||||
if (config == MPS_BOOT_LEGACY) {
|
||||
cfg = 0x00020000;
|
||||
fw_size -= sizeof(uint32_t);
|
||||
} else {
|
||||
if(config == MPS_BOOT_ENCRYPTED) {
|
||||
cfg = __raw_readl(mps->mbox_base + MPS_CPU1_CFG_STAT);
|
||||
cfg |= 0x00700000;
|
||||
} else {
|
||||
printk("PANIC!\n");
|
||||
}
|
||||
}
|
||||
|
||||
mps_reset();
|
||||
|
||||
memcpy_toio(mps->cp1_base, data, size);
|
||||
|
||||
__raw_writel(cfg, mps->mbox_base + MPS_CPU1_CFG_STAT);
|
||||
__raw_writel(fw_size, mps->mbox_base + MPS_CPU1_BOOT_SIZE);
|
||||
__raw_writel((uint32_t)mps->cp1_base, mps->mbox_base + MPS_CPU1_BOOT_RVEC);
|
||||
|
||||
mps_release();
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mps_load_firmware);
|
||||
|
||||
void mps_configure_fifo(struct mps *mps, struct mps_fifo *fifo,
|
||||
const struct mps_fifo_config *config)
|
||||
{
|
||||
mps_fifo_init(fifo, mps->mbox_base + config->base,
|
||||
mps->mbox_base + config->head_addr,
|
||||
mps->mbox_base + config->tail_addr,
|
||||
config->size);
|
||||
|
||||
__raw_writel(config->size, mps->mbox_base + config->size_addr);
|
||||
__raw_writel(mps->mbox_res->start + config->base,
|
||||
mps->mbox_base + config->base_addr);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mps_configure_fifo);
|
||||
|
||||
void mps_configure_mailbox(struct mps *mps, struct mps_mailbox *mbox,
|
||||
const struct mps_fifo_config *upstream_config,
|
||||
const struct mps_fifo_config *downstream_config)
|
||||
{
|
||||
mps_configure_fifo(mps, &mbox->upstream, upstream_config);
|
||||
mps_configure_fifo(mps, &mbox->downstream, downstream_config);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mps_configure_mailbox);
|
||||
|
||||
static int __devinit mps_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret;
|
||||
struct mps *mps;
|
||||
struct resource *res;
|
||||
|
||||
mps = kzalloc(sizeof(*mps), GFP_KERNEL);
|
||||
|
||||
if (!mps)
|
||||
return -ENOMEM;
|
||||
|
||||
mps->dev = &pdev->dev;
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mem");
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "Failed to get mem resource");
|
||||
ret = -ENOENT;
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
res = request_mem_region(res->start, resource_size(res),
|
||||
dev_name(&pdev->dev));
|
||||
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "Failed to request mem resource");
|
||||
ret = -EBUSY;
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
mps->base = ioremap_nocache(res->start, resource_size(res));
|
||||
|
||||
if (!mps->base) {
|
||||
dev_err(&pdev->dev, "Failed to ioremap mem region\n");
|
||||
ret = -EBUSY;
|
||||
goto err_release_mem_region;
|
||||
}
|
||||
|
||||
mps->res = res;
|
||||
|
||||
|
||||
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mailbox");
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "Failed to get mailbox mem region\n");
|
||||
ret = -ENOENT;
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
res = request_mem_region(res->start, resource_size(res),
|
||||
dev_name(&pdev->dev));
|
||||
|
||||
if (!res) {
|
||||
dev_err(&pdev->dev, "Failed to request mailbox mem region\n");
|
||||
ret = -EBUSY;
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
mps->mbox_base = ioremap_nocache(res->start, resource_size(res));
|
||||
|
||||
if (!mps->mbox_base) {
|
||||
dev_err(&pdev->dev, "Failed to ioremap mailbox mem region\n");
|
||||
ret = -EBUSY;
|
||||
goto err_release_mem_region;
|
||||
}
|
||||
|
||||
mps->mbox_res = res;
|
||||
|
||||
mps->cp1_base = ioremap_nocache((unsigned int)pdev->dev.platform_data, 1 << 20);
|
||||
|
||||
if (!mps->cp1_base) {
|
||||
dev_err(&pdev->dev, "Failed to ioremap cp1 address\n");
|
||||
ret = -EBUSY;
|
||||
goto err_release_mem_region;
|
||||
}
|
||||
|
||||
mps->irq_ad0 = INT_NUM_IM4_IRL18;
|
||||
mps->irq_ad1 = INT_NUM_IM4_IRL19;
|
||||
mps->irq_base = 160;
|
||||
|
||||
ret = mps_irq_init(mps);
|
||||
if (ret < 0)
|
||||
goto err_iounmap;
|
||||
|
||||
platform_set_drvdata(pdev, mps);
|
||||
|
||||
return 0;
|
||||
|
||||
err_iounmap:
|
||||
iounmap(mps->mbox_base);
|
||||
err_release_mem_region:
|
||||
release_mem_region(res->start, resource_size(res));
|
||||
err_free:
|
||||
kfree(mps);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit mps_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct mps *mps = platform_get_drvdata(pdev);
|
||||
|
||||
mps_irq_exit(mps);
|
||||
|
||||
iounmap(mps->mbox_base);
|
||||
release_mem_region(mps->mbox_res->start, resource_size(mps->mbox_res));
|
||||
iounmap(mps->base);
|
||||
release_mem_region(mps->res->start, resource_size(mps->res));
|
||||
|
||||
kfree(mps);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver mps_driver = {
|
||||
.probe = mps_probe,
|
||||
.remove = __devexit_p(mps_remove),
|
||||
.driver = {
|
||||
.name = "mps",
|
||||
.owner = THIS_MODULE
|
||||
},
|
||||
};
|
||||
|
||||
static int __init mps_init(void)
|
||||
{
|
||||
return platform_driver_register(&mps_driver);
|
||||
}
|
||||
module_init(mps_init);
|
||||
|
||||
static void __exit mps_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&mps_driver);
|
||||
}
|
||||
module_exit(mps_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
|
|
@ -1,102 +0,0 @@
|
|||
#include <linux/io.h>
|
||||
|
||||
#include "mps.h"
|
||||
|
||||
void mps_fifo_init(struct mps_fifo *fifo, void __iomem *base,
|
||||
void __iomem *head_addr, void __iomem *tail_addr, uint32_t size)
|
||||
{
|
||||
fifo->base = base;
|
||||
fifo->head_addr = head_addr;
|
||||
fifo->tail_addr = tail_addr;
|
||||
fifo->size = size;
|
||||
mps_fifo_reset(fifo);
|
||||
}
|
||||
|
||||
void mps_fifo_in(struct mps_fifo *fifo, const uint32_t *from, size_t len)
|
||||
{
|
||||
uint32_t head = __raw_readl(fifo->head_addr);
|
||||
void __iomem *base = fifo->base + head;
|
||||
size_t i = 0;
|
||||
size_t byte_len = len * 4;
|
||||
|
||||
if (head < byte_len) {
|
||||
for(; i <= head / 4; ++i) {
|
||||
__raw_writel(from[i], base);
|
||||
base -= 4;
|
||||
}
|
||||
|
||||
base += fifo->size;
|
||||
head += fifo->size;
|
||||
}
|
||||
|
||||
for(; i < len; ++i) {
|
||||
__raw_writel(from[i], base);
|
||||
base -= 4;
|
||||
}
|
||||
|
||||
head -= byte_len;
|
||||
__raw_writel(head, fifo->head_addr);
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mps_fifo_in);
|
||||
|
||||
void mps_fifo_out(struct mps_fifo *fifo, uint32_t *to, size_t len)
|
||||
{
|
||||
uint32_t tail = __raw_readl(fifo->tail_addr);
|
||||
void __iomem *base = fifo->base + tail;
|
||||
size_t i = 0;
|
||||
size_t byte_len = len * 4;
|
||||
|
||||
if (tail < byte_len) {
|
||||
for(; i <= tail / 4; ++i) {
|
||||
to[i] = __raw_readl(base);
|
||||
base -= 4;
|
||||
}
|
||||
|
||||
base += fifo->size;
|
||||
tail += fifo->size;
|
||||
}
|
||||
|
||||
for(; i < len; ++i) {
|
||||
to[i] = __raw_readl(base);
|
||||
base -= 4;
|
||||
}
|
||||
|
||||
tail -= byte_len;
|
||||
__raw_writel(tail, fifo->tail_addr);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mps_fifo_out);
|
||||
|
||||
uint32_t mps_fifo_peek(struct mps_fifo *fifo)
|
||||
{
|
||||
uint32_t tail = __raw_readl(fifo->tail_addr);
|
||||
void __iomem *base = fifo->base + tail;
|
||||
return __raw_readl(base);
|
||||
}
|
||||
|
||||
void mps_fifo_reset(struct mps_fifo *fifo)
|
||||
{
|
||||
void __iomem *base = fifo->base + fifo->size - 4;
|
||||
size_t i;
|
||||
|
||||
__raw_writel(fifo->size - 4, fifo->head_addr);
|
||||
__raw_writel(fifo->size - 4, fifo->tail_addr);
|
||||
|
||||
for(i = 0; i < 16; ++i) {
|
||||
__raw_writel(0x0, base);
|
||||
base -= 4;
|
||||
}
|
||||
}
|
||||
|
||||
size_t mps_fifo_len(struct mps_fifo *fifo)
|
||||
{
|
||||
uint32_t head = __raw_readl(fifo->head_addr);
|
||||
uint32_t tail = __raw_readl(fifo->tail_addr);
|
||||
|
||||
if (tail < head)
|
||||
return head - tail;
|
||||
else
|
||||
return fifo->size - (tail - head);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(mps_fifo_len);
|
||||
|
|
@ -1,157 +0,0 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/kernel_stat.h>
|
||||
#include <ifxmips_irq.h>
|
||||
|
||||
#include "mps.h"
|
||||
#include "mps-irq.h"
|
||||
|
||||
#define MPS_REG_AD0_IRQ_BASE 0x40
|
||||
#define MPS_REG_AD1_IRQ_BASE 0x44
|
||||
|
||||
#define MPS_REG_AD_IRQ_STATUS 0x00
|
||||
#define MPS_REG_AD_IRQ_SET 0x08
|
||||
#define MPS_REG_AD_IRQ_CLEAR 0x10
|
||||
#define MPS_REG_AD_IRQ_ENABLE 0x18
|
||||
|
||||
struct mps_irq_desc
|
||||
{
|
||||
void __iomem *base;
|
||||
unsigned int irq_base;
|
||||
};
|
||||
|
||||
static inline unsigned int mps_irq_bit(struct mps_irq_desc *mps_desc, int irq)
|
||||
{
|
||||
return BIT(irq - mps_desc->irq_base);
|
||||
}
|
||||
|
||||
static void mps_irq_ack(unsigned int irq)
|
||||
{
|
||||
struct mps_irq_desc *mps_desc = get_irq_chip_data(irq);
|
||||
|
||||
__raw_writel(mps_irq_bit(mps_desc, irq),
|
||||
mps_desc->base + MPS_REG_AD_IRQ_CLEAR);
|
||||
}
|
||||
|
||||
static void mps_irq_mask(unsigned int irq)
|
||||
{
|
||||
struct mps_irq_desc *mps_desc = get_irq_chip_data(irq);
|
||||
uint32_t mask;
|
||||
|
||||
mask = __raw_readl(mps_desc->base + MPS_REG_AD_IRQ_ENABLE);
|
||||
mask &= ~mps_irq_bit(mps_desc, irq);
|
||||
__raw_writel(mask, mps_desc->base + MPS_REG_AD_IRQ_ENABLE);
|
||||
}
|
||||
|
||||
static void mps_irq_unmask(unsigned int irq)
|
||||
{
|
||||
struct mps_irq_desc *mps_desc = get_irq_chip_data(irq);
|
||||
uint32_t mask;
|
||||
|
||||
mask = __raw_readl(mps_desc->base + MPS_REG_AD_IRQ_ENABLE);
|
||||
mask |= mps_irq_bit(mps_desc, irq) | 0xffff;
|
||||
__raw_writel(mask, mps_desc->base + MPS_REG_AD_IRQ_ENABLE);
|
||||
}
|
||||
|
||||
static struct irq_chip mps_irq_chip = {
|
||||
.name = "mps",
|
||||
.ack = mps_irq_ack,
|
||||
.mask = mps_irq_mask,
|
||||
.unmask = mps_irq_unmask,
|
||||
};
|
||||
|
||||
static void mps_irq_demux_handler(unsigned int irq, struct irq_desc *desc)
|
||||
{
|
||||
struct mps_irq_desc *mps_desc = get_irq_data(irq);
|
||||
uint32_t val;
|
||||
int mps_irq;
|
||||
|
||||
desc->chip->mask(irq);
|
||||
|
||||
val = __raw_readl(mps_desc->base + MPS_REG_AD_IRQ_STATUS);
|
||||
mps_irq = ffs(val);
|
||||
|
||||
/* printk("irq: %d %x\n", mps_irq, val);*/
|
||||
|
||||
if (mps_irq > 16)
|
||||
printk("PANIC!\n");
|
||||
|
||||
if (mps_irq)
|
||||
generic_handle_irq(mps_irq + mps_desc->irq_base - 1);
|
||||
|
||||
desc->chip->ack(irq);
|
||||
desc->chip->unmask(irq);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
static const uint32_t ring_msg[] = {
|
||||
0x01010004, 0x00030000,
|
||||
};
|
||||
|
||||
static irqreturn_t mps_irq_ad0(int irq, void *devid)
|
||||
{
|
||||
struct mps *mps = devid;
|
||||
uint32_t val;
|
||||
|
||||
val = __raw_readl(mps->base + MPS_REG_AD0_IRQ_STATUS);
|
||||
printk("WOHO ein IRQ: %x\n", val);
|
||||
__raw_writel(val, mps->base + MPS_REG_AD0_IRQ_CLEAR);
|
||||
|
||||
if (val & BIT(MPS_IRQ_DOWNLOAD_DONE))
|
||||
complete(&mps->init_completion);
|
||||
|
||||
if (val & BIT(MPS_IRQ_EVENT))
|
||||
mps_fifo_in(&mps->mbox_cmd.downstream, ring_msg, ARRAY_SIZE(ring_msg));
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define MPS_NUM_AD_IRQS 32
|
||||
|
||||
struct mps_irq_desc mps_irq_descs[2];
|
||||
|
||||
int mps_irq_init(struct mps *mps)
|
||||
{
|
||||
int ret = 0;
|
||||
int irq;
|
||||
|
||||
mps_irq_descs[0].base = mps->base + MPS_REG_AD0_IRQ_BASE;
|
||||
mps_irq_descs[0].irq_base = mps->irq_base;
|
||||
mps_irq_descs[1].base = mps->base + MPS_REG_AD1_IRQ_BASE;
|
||||
mps_irq_descs[1].irq_base = mps->irq_base + 16;
|
||||
|
||||
|
||||
set_irq_data(mps->irq_ad0, &mps_irq_descs[0]);
|
||||
set_irq_chained_handler(mps->irq_ad0, mps_irq_demux_handler);
|
||||
set_irq_data(mps->irq_ad1, &mps_irq_descs[1]);
|
||||
set_irq_chained_handler(mps->irq_ad1, mps_irq_demux_handler);
|
||||
|
||||
/*
|
||||
ret = request_irq(mps->irq_ad0, mps_irq_demux_handler, IRQF_DISABLED,
|
||||
"mps ad0", &mps_irq_descs[0]);
|
||||
ret = request_irq(mps->irq_ad1, mps_irq_demux_handler, IRQF_DISABLED,
|
||||
"mps ad0", &mps_irq_descs[1]);
|
||||
*/
|
||||
for (irq = 0; irq < MPS_NUM_AD_IRQS; ++irq) {
|
||||
set_irq_chip_data(irq + mps->irq_base, &mps_irq_descs[irq / 16]);
|
||||
set_irq_chip_and_handler(irq + mps->irq_base, &mps_irq_chip, handle_level_irq);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
res = request_irq(INT_NUM_IM4_IRL18, mps_irq_ad0, IRQF_DISABLED,
|
||||
"mps ad0", mps);
|
||||
|
||||
irqs = BIT(MPS_IRQ_CMD_UPSTREAM) | BIT(MPS_IRQ_DATA_UPSTREAM)
|
||||
| BIT(MPS_IRQ_DOWNLOAD_DONE) | BIT(MPS_IRQ_EVENT) | BIT(MPS_IRQ_CMD_ERROR);
|
||||
|
||||
__raw_writel(irqs, mps->base + MPS_REG_AD0_IRQ_ENA);
|
||||
*/
|
||||
return ret;
|
||||
}
|
||||
|
||||
void mps_irq_exit(struct mps *mps)
|
||||
{
|
||||
free_irq(INT_NUM_IM4_IRL18, mps);
|
||||
}
|
|
@ -1,18 +0,0 @@
|
|||
|
||||
#define MPS_IRQ_BASE 160
|
||||
#define MPS_IRQ(x) (MPS_IRQ_BASE + (x))
|
||||
#define MPS_IRQ_CMD_UPSTREAM MPS_IRQ(0)
|
||||
#define MPS_IRQ_DATA_UPSTREAM MPS_IRQ(1)
|
||||
#define MPS_IRQ_CMD_DOWNSTREAM MPS_IRQ(2)
|
||||
#define MPS_IRQ_DATA_DOWNSTREAM MPS_IRQ(3)
|
||||
#define MPS_IRQ_RCV_OVERFLOW MPS_IRQ(4)
|
||||
#define MPS_IRQ_EVENT MPS_IRQ(5)
|
||||
#define MPS_IRQ_EVENT_OVERFLOW MPS_IRQ(6)
|
||||
#define MPS_IRQ_CMD_ERROR MPS_IRQ(8)
|
||||
#define MPS_IRQ_PCM_CRASH MPS_IRQ(9)
|
||||
#define MPS_IRQ_DATA_ERROR MPS_IRQ(10)
|
||||
#define MPS_IRQ_MIPS_OL MPS_IRQ(11)
|
||||
#define MPS_IRQ_WATCHDOG_FAIL MPS_IRQ(14)
|
||||
#define MPS_IRQ_DOWNLOAD_DONE MPS_IRQ(15)
|
||||
|
||||
|
|
@ -1,19 +0,0 @@
|
|||
|
||||
|
||||
int mps_message_send(struct mps_fifo *fifo, struct mps_message *msg)
|
||||
{
|
||||
}
|
||||
|
||||
int mps_message_recv(struct mps_fifo *fifo, struct mps_message *msg)
|
||||
{
|
||||
mps_fifo_out(fifo, &msg->header, sizeof(msg->header));
|
||||
mps_fifo_out(fifo, &msg->data, mps_message_size(msg));
|
||||
}
|
||||
|
||||
struct mps_message *msg mps_message_recv_alloc(struct mps_fifo *fifo)
|
||||
{
|
||||
struct mps_message *msg;
|
||||
|
||||
mps_fifo_out(fifo, &msg->header, sizeof(msg->header));
|
||||
mps_fifo_out(fifo, &msg->data, mps_message_size(msg));
|
||||
}
|
|
@ -1,87 +0,0 @@
|
|||
#ifndef __MPS_MSG_H__
|
||||
#define __MPS_MSG_H__
|
||||
|
||||
#include <linux/slab.h>
|
||||
|
||||
struct mps_message {
|
||||
uint32_t header;
|
||||
uint32_t data[0];
|
||||
};
|
||||
|
||||
#define MPS_MSG_HEADER(_rw, _sc, _bc, _cmd, _chan, _mode, _ecmd, _length) \
|
||||
(((_rw) << 31) | ((_sc) << 30) | ((_bc) << 29) | ((_cmd) << 24) | \
|
||||
((_chan) << 16) | ((_mode) << 13) | ((_ecmd) << 8) | (_length))
|
||||
|
||||
#define MPS_MSG_INIT(_msg, _rw, _sc, _bc, _cmd, _chan, _mode, _ecmd, _length) \
|
||||
do { \
|
||||
(_msg)->header = MPS_MSG_HEADER(_rw, _sc, _bc, _cmd, _chan, _mode, \
|
||||
_ecmd, _length); \
|
||||
} while(0)
|
||||
|
||||
|
||||
static inline void mps_msg_init(struct mps_message *msg, uint32_t rw, uint32_t sc,
|
||||
uint32_t bc, uint32_t cmd, uint32_t chan, uint32_t mode, uint32_t ecmd,
|
||||
uint32_t length)
|
||||
{
|
||||
msg->header = MPS_MSG_HEADER(rw, sc, bc, cmd, chan, mode, ecmd, length);
|
||||
}
|
||||
|
||||
#define DECLARE_MESSAGE(_name, _size) struct mps_message _name; \
|
||||
uint32_t __mps_msg_data_ ## __FUNCTION__ ## __LINE__[_size]
|
||||
|
||||
static inline struct mps_message *mps_message_alloc(size_t size)
|
||||
{
|
||||
return kmalloc(sizeof(struct mps_message) + size * sizeof(uint32_t), GFP_KERNEL);
|
||||
}
|
||||
|
||||
static inline size_t mps_message_size(const struct mps_message *msg)
|
||||
{
|
||||
return msg->header & 0xff;
|
||||
}
|
||||
|
||||
enum {
|
||||
MPS_MSG_WRITE = 0,
|
||||
MPS_MSG_READ = 1,
|
||||
};
|
||||
|
||||
enum {
|
||||
MPS_CMD_ALI = 1,
|
||||
MPS_CMD_DECT = 3,
|
||||
MPS_CMD_SDD = 4,
|
||||
MPS_CMD_EOP = 6,
|
||||
};
|
||||
|
||||
#define MOD_PCM 0
|
||||
#define MOD_SDD 0
|
||||
#define MOD_ALI 1
|
||||
#define MOD_SIGNALING 2
|
||||
#define MOD_CODER 3
|
||||
#define MOD_RESOURCE 6
|
||||
#define MOD_SYSTEM 7
|
||||
#define ECMD_SYS_VER 6
|
||||
#define SYS_CAP_ECMD 7
|
||||
#define ECMD_CIDS_DATA 9
|
||||
#define ECMD_DCCTL_DEBUG 0x0a
|
||||
|
||||
#define ALI_CHAN_CMD 6
|
||||
#define ALI_CHAN_ECMD 1
|
||||
|
||||
#define MPS_MSG_HEADER_W(_sc, _bc, _cmd, _chan, _mode, _ecmd, _length) \
|
||||
MPS_MSG_HEADER(MPS_MSG_WRITE, _sc, _bc, _cmd, _chan, _mode, _ecmd, _length)
|
||||
|
||||
#define MPS_MSG_HEADER_R(_sc, _bc, _cmd, _chan, _mode, _ecmd, _length) \
|
||||
MPS_MSG_HEADER(MPS_MSG_READ, _sc, _bc, _cmd, _chan, _mode, _ecmd, _length)
|
||||
|
||||
#define MPS_MSG_CMD_EOP(_mode, _ecmd, _length) \
|
||||
MPS_MSG_HEADER_R(0, 0, MPS_CMD_EOP, 0, _mode, _ecmd, _length)
|
||||
|
||||
#define MPS_MSG_CMD_EOP_SYSTEM(_ecmd, _length) \
|
||||
MPS_MSG_CMD_EOP(MOD_SYSTEM, _ecmd, _length)
|
||||
|
||||
#define MPS_CMD_GET_VERSION \
|
||||
MPS_MSG_CMD_EOP_SYSTEM(ECMD_SYS_VER, 4)
|
||||
|
||||
#define MPS_CMD_ALI(_chan) \
|
||||
MPS_MSG_HEADER_W(0, 0, ALI_CHAN_CMD, _chan, MOD_ALI, ALI_CHAN_ECMD, 12)
|
||||
|
||||
#endif
|
|
@ -1,85 +0,0 @@
|
|||
#ifndef __MPS_H__
|
||||
#define __MPS_H__
|
||||
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/completion.h>
|
||||
|
||||
struct mps_fifo_config
|
||||
{
|
||||
size_t head_addr;
|
||||
size_t tail_addr;
|
||||
size_t base_addr;
|
||||
size_t size_addr;
|
||||
|
||||
size_t base;
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct mps_fifo {
|
||||
void __iomem *base;
|
||||
void __iomem *head_addr;
|
||||
void __iomem *tail_addr;
|
||||
uint32_t size;
|
||||
};
|
||||
|
||||
struct mps_mailbox {
|
||||
struct mps_fifo upstream;
|
||||
struct mps_fifo downstream;
|
||||
};
|
||||
|
||||
enum mps_boot_config
|
||||
{
|
||||
MPS_BOOT_LEGACY = 1,
|
||||
MPS_BOOT_ENCRYPTED = 2,
|
||||
};
|
||||
|
||||
struct mps {
|
||||
struct resource *res;
|
||||
void __iomem *base;
|
||||
|
||||
struct resource *mbox_res;
|
||||
void __iomem *mbox_base;
|
||||
|
||||
struct resource *cp1_res;
|
||||
void __iomem *cp1_base;
|
||||
|
||||
struct device *dev;
|
||||
|
||||
int irq_ad0;
|
||||
int irq_ad1;
|
||||
int irq_base;
|
||||
};
|
||||
|
||||
void mps_configure_fifo(struct mps *mps, struct mps_fifo *fifo,
|
||||
const struct mps_fifo_config *config);
|
||||
|
||||
void mps_configure_mailbox(struct mps *mps, struct mps_mailbox *mbox,
|
||||
const struct mps_fifo_config *upstream_config,
|
||||
const struct mps_fifo_config *downstream_config);
|
||||
|
||||
void mps_load_firmware(struct mps *mps, const void *data, size_t size,
|
||||
enum mps_boot_config config);
|
||||
|
||||
static inline struct mps *device_to_mps(struct device *dev)
|
||||
{
|
||||
return (struct mps *)dev_get_drvdata(dev);
|
||||
}
|
||||
|
||||
/* fifo */
|
||||
void mps_fifo_init(struct mps_fifo *fifo, void __iomem *data_addr,
|
||||
void __iomem *head_addr, void __iomem *tail_addr, uint32_t size);
|
||||
void mps_fifo_in(struct mps_fifo *fifo, const uint32_t *from, size_t len);
|
||||
void mps_fifo_out(struct mps_fifo *fifo, uint32_t *to, size_t len);
|
||||
uint32_t mps_fifo_peek(struct mps_fifo *fifo);
|
||||
void mps_fifo_reset(struct mps_fifo *fifo);
|
||||
size_t mps_fifo_len(struct mps_fifo *fifo);
|
||||
|
||||
/* Mailbox */
|
||||
int mps_mailbox_init(struct mps_mailbox *mbox, const char *name, int irq);
|
||||
int mps_mailbox_command_read(struct mps_mailbox *mbox, uint32_t cmd,
|
||||
uint32_t *result);
|
||||
int mps_mailbox_command_write(struct mps_mailbox *mbox, uint32_t cmd,
|
||||
const uint32_t *data);
|
||||
|
||||
|
||||
#endif
|
|
@ -1,129 +0,0 @@
|
|||
#include <linux/kernel.h>
|
||||
|
||||
#include "vmmc.h"
|
||||
#include "vmmc-cmds.h"
|
||||
#include "vmmc-alm.h"
|
||||
#include "vmmc-module.h"
|
||||
#include "mps.h"
|
||||
|
||||
static inline struct vmmc_alm *vmmc_module_to_alm(struct vmmc_module *module)
|
||||
{
|
||||
return container_of(module, struct vmmc_alm, module);
|
||||
}
|
||||
|
||||
int vmmc_alm_set_state(struct vmmc_alm *alm, enum vmmc_alm_state state)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = vmmc_command_write(alm->vmmc, VMMC_CMD_OPMODE(alm->id), &state);
|
||||
if (!ret)
|
||||
alm->state = state;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
enum vmmc_alm_state vmmc_alm_get_state(struct vmmc_alm *alm)
|
||||
{
|
||||
return alm->state;
|
||||
}
|
||||
|
||||
static struct vmmc_alm_coef *vmmc_alm_coef_alloc(unsigned int offset, size_t len)
|
||||
{
|
||||
struct vmmc_alm_coef *coef;
|
||||
|
||||
coef = kzalloc(sizeof(*coef) + sizeof(uint32_t) * DIV_ROUND_UP(len, 4),
|
||||
GFP_KERNEL);
|
||||
coef->offset = offset;
|
||||
coef->len = len;
|
||||
|
||||
return coef;
|
||||
}
|
||||
|
||||
int vmcc_alm_set_coefficents(struct vmmc_alm *alm,
|
||||
const struct vmmc_alm_coef *coef_list)
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t cmd;
|
||||
struct vmmc_alm_coef *coef;
|
||||
struct list_head l;
|
||||
|
||||
INIT_LIST_HEAD(&l);
|
||||
|
||||
coef = vmmc_alm_coef_alloc(0x37, 8);
|
||||
coef->data[0] = 0x76d7871d;
|
||||
coef->data[1] = 0x7fbb7ff4;
|
||||
list_add_tail(&coef->list, &l);
|
||||
coef = vmmc_alm_coef_alloc(0x5e, 2);
|
||||
coef->data[0] = 0x7e000000;
|
||||
list_add_tail(&coef->list, &l);
|
||||
coef = vmmc_alm_coef_alloc(0x6c, 2);
|
||||
coef->data[0] = 0x7e000000;
|
||||
list_add_tail(&coef->list, &l);
|
||||
|
||||
list_for_each_entry(coef, &l, list) {
|
||||
cmd = VMMC_CMD_ALM_COEF(alm->id, coef->offset, coef->len);
|
||||
ret = vmmc_command_write(alm->vmmc, cmd, coef->data);
|
||||
if (ret)
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int vmmc_alm_sync(struct vmmc_module *module)
|
||||
{
|
||||
struct vmmc_alm *alm = vmmc_module_to_alm(module);
|
||||
|
||||
alm->cmd_cache[0] = VMMC_CMD_ALI_DATA1(1, 0, 0, 1, 0, module->pins[0], 0x4000);
|
||||
alm->cmd_cache[1] = VMMC_CMD_ALI_DATA2(0x4000, module->pins[1], module->pins[2]);
|
||||
alm->cmd_cache[2] = VMMC_CMD_ALI_DATA3(module->pins[3], module->pins[4]);
|
||||
|
||||
return vmmc_command_write(alm->vmmc, VMMC_CMD_ALI(alm->id), alm->cmd_cache);
|
||||
}
|
||||
|
||||
static int vmmc_alm_enable(struct vmmc_module *module, bool enable)
|
||||
{
|
||||
struct vmmc_alm *alm = vmmc_module_to_alm(module);
|
||||
|
||||
return vmmc_command_write(alm->vmmc, VMMC_CMD_ALI(alm->id), alm->cmd_cache);
|
||||
}
|
||||
|
||||
static const struct vmmc_module_ops vmmc_alm_module_ops = {
|
||||
.sync = vmmc_alm_sync,
|
||||
.enable = vmmc_alm_enable,
|
||||
};
|
||||
|
||||
int vmmc_alm_init(struct vmmc_alm *alm, struct vmmc *vmmc, unsigned int id)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = vmmc_module_init(&alm->module, 5, &vmmc_alm_module_ops);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
alm->id = id;
|
||||
alm->module.id = id + 0x4;
|
||||
alm->vmmc = vmmc;
|
||||
|
||||
alm->cmd_cache[0] = VMMC_CMD_ALI_DATA1(1, 0, 0, 1, 0, 0, 0x2000);
|
||||
alm->cmd_cache[1] = VMMC_CMD_ALI_DATA2(0x2000, 0, 0);
|
||||
alm->cmd_cache[2] = VMMC_CMD_ALI_DATA3(0, 0);
|
||||
|
||||
vmmc_command_write(alm->vmmc, VMMC_CMD_ALI(alm->id), alm->cmd_cache);
|
||||
vmcc_alm_set_coefficents(alm, NULL);
|
||||
vmmc_register_module(vmmc, &alm->module);
|
||||
|
||||
// disable lec
|
||||
// write lec coef
|
||||
// write nlp coef
|
||||
// enable lec
|
||||
|
||||
// ALI_LEC ALI_ES RES_LEC_COEF RES_LEC_NLP_COEF
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void vmmc_alm_hook_event_handler(struct vmmc *vmmc, uint32_t id, uint32_t data)
|
||||
{
|
||||
tapi_report_hook_event(&vmmc->tdev, &vmmc->tdev.ports[id], data & 1);
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
#ifndef __VMMC_ALM_H__
|
||||
#define __VMMC_ALM_H__
|
||||
|
||||
#include "vmmc-module.h"
|
||||
|
||||
struct vmmc;
|
||||
enum vmmc_alm_state {
|
||||
VMMC_ALM_STATE_OFF = 0 << 16,
|
||||
VMMC_ALM_STATE_ONHOOK = 1 << 16,
|
||||
VMMC_ALM_STATE_RING = 3 << 16,
|
||||
VMMC_ALM_STATE_ACTIVE = 2 << 16,
|
||||
};
|
||||
|
||||
struct vmmc_alm {
|
||||
struct vmmc *vmmc;
|
||||
unsigned int id;
|
||||
|
||||
enum vmmc_alm_state state;
|
||||
|
||||
struct vmmc_module module;
|
||||
|
||||
uint32_t cmd_cache[3];
|
||||
};
|
||||
|
||||
struct vmmc_alm_coef {
|
||||
struct list_head list;
|
||||
unsigned int offset;
|
||||
size_t len;
|
||||
uint32_t data[0];
|
||||
};
|
||||
|
||||
int vmmc_alm_init(struct vmmc_alm *alm, struct vmmc *vmmc, unsigned int id);
|
||||
|
||||
int vmmc_alm_set_state(struct vmmc_alm *alm, enum vmmc_alm_state state);
|
||||
enum vmmc_alm_state vmmc_alm_get_state(struct vmmc_alm *alm);
|
||||
|
||||
int vmcc_alm_set_coefficents(struct vmmc_alm *alm,
|
||||
const struct vmmc_alm_coef *coef_list);
|
||||
|
||||
void vmmc_alm_hook_event_handler(struct vmmc *vmmc, uint32_t event, uint32_t data);
|
||||
|
||||
#endif
|
|
@ -1,98 +0,0 @@
|
|||
#ifndef __VMMC_CMDS_H__
|
||||
#define __VMMC_CMDS_H__
|
||||
|
||||
#define _VMMC_CMD(_x) ((_x) << 24)
|
||||
#define _VMMC_MOD(_x) ((_x) << 13)
|
||||
#define _VMMC_ECMD(_x) ((_x) << 8)
|
||||
|
||||
#define _VMMC_MSG(_cmd, _mod, _ecmd) \
|
||||
(_VMMC_CMD(_cmd) | _VMMC_ECMD(_ecmd) | _VMMC_MOD(_mod))
|
||||
|
||||
#define _VMMC_CHAN(_chan) ((_chan) << 16)
|
||||
#define _VMMC_LENGTH(_length) ((_length) << 2)
|
||||
|
||||
#define VMMC_CMD_OPMODE(_chan) (_VMMC_MSG(1, 0, 0) | _VMMC_CHAN(_chan) | _VMMC_LENGTH(1))
|
||||
|
||||
#define VMMC_CMD_SIG(_chan) (_VMMC_MSG(6, 2, 1) | _VMMC_CHAN(_chan) | _VMMC_LENGTH(1))
|
||||
#define VMMC_CMD_SIG_DATA(_enable, _event, _rate, _i1, _i2, _mute1, _mute2) \
|
||||
(((_enable) << 31) | ((_event) << 30) | ((_i1) << 24) | ((_i2) << 16) | \
|
||||
((_rate) << 23) | ((_mute1) << 15) | ((_mute2) << 14))
|
||||
|
||||
#define VMMC_CMD_SIG_SET_ENABLE(_data, _enable) (((_data) & ~BIT(31)) | ((_enable) << 31))
|
||||
#define VMMC_CMD_SIG_SET_INPUTS(_data, _i1, _i2) (((_data) & ~0x3f3f0000) | \
|
||||
((_i1) << 24) | ((_i2) << 16))
|
||||
|
||||
#define VMMC_CMD_DTMFR(_chan) (_VMMC_MSG(6, 2, 4) | _VMMC_CHAN(_chan) | _VMMC_LENGTH(1))
|
||||
#define VMMC_CMD_DTMFR_DATA(_enable, _event, _nr) \
|
||||
(((_enable) << 31) | ((_event) << 30) | (6 << 27) | ((_nr) << 16))
|
||||
|
||||
#define VMMC_CMD_CODER(_chan) (_VMMC_MSG(6, 3, 1) | _VMMC_CHAN(_chan) | _VMMC_LENGTH(4))
|
||||
|
||||
#define VMMC_CMD_CODER_DATA1(_enable, _rate, _ns, _pte, _nr, _i1, _hp, _pf, \
|
||||
_cng, _bfi, _dec, _im, _pst, _sic, _em, _enc) \
|
||||
(((_enable) << 31) | ((_rate) << 30) | ((_ns) << 29) | ((_pte) << 26) | \
|
||||
((_nr) << 22) | ((_i1) << 16) | ((_hp) << 15) | ((_pf) << 14) | \
|
||||
((_cng) << 13) | ((_bfi) << 12) | ((_dec) << 11) | ((_im) << 10) | \
|
||||
((_pst) << 9) | ((_sic) << 8) | ((_em) << 7) | (_enc))
|
||||
|
||||
#define VMMC_CMD_CODER_DATA2(_gain1, _gain2) (((_gain1) << 16) | (_gain2))
|
||||
|
||||
#define VMMC_CMD_CODER_DATA3(_de, _ee, _i2, _red, _i3, _plc, _i4, _i5) \
|
||||
(((_de) << 31) | ((_ee) << 30) | ((_i2) << 24) | ((_red) << 22) | \
|
||||
((_i3) << 16) | ((_plc) << 15) | ((_i4) << 8) | (_i5))
|
||||
|
||||
#define VMMC_CMD_SERR_ACK(_chan) _VMMC_MSG(6, 7, 1) | _VMMC_CHAN(_chan) | _VMMC_LENGTH(1)
|
||||
|
||||
#define VMMC_CMD_SERR_ACK_DATA1(_foo) ((_foo) << 22)
|
||||
|
||||
#define VMMC_CMD_CODER_DATA4(_tsf) ((_tsf) << 31)
|
||||
|
||||
#define VMMC_EVENT_ID_MASK (_VMMC_MSG(0x1f, 0x7, 0x1f) | 0xff)
|
||||
|
||||
#define VMMC_MSG_GET_CHAN(_msg) (((_msg) >> 16) & 0x1f)
|
||||
|
||||
#define VMMC_EVENT_HOOK_STATE(_data) ((_data) & 1)
|
||||
|
||||
#define VMMC_EVENT_HOOK_ID (_VMMC_MSG(9, 1, 1) | _VMMC_LENGTH(1))
|
||||
#define VMMC_EVENT_DTMF_ID (_VMMC_MSG(9, 2, 0) | _VMMC_LENGTH(1))
|
||||
|
||||
#define VMMC_VOICE_DATA(_type, _chan, _len) (((_type) << 24) | ((_chan) << 16) \
|
||||
| (_len))
|
||||
|
||||
|
||||
#define VMMC_CMD_ALI(_chan) (_VMMC_MSG(6, 1, 1) | _VMMC_CHAN(_chan) | _VMMC_LENGTH(3))
|
||||
|
||||
#define VMMC_CMD_ALI_DATA1(_enable, _rate, _ud, _eh, _eo, _i1, _dg1) \
|
||||
(((_enable) << 31) | ((_rate) << 30) | ((_ud) << 29) | ((_eh) << 27) | \
|
||||
((_eo) << 26) | ((_i1) << 16) | (_dg1))
|
||||
|
||||
#define VMMC_CMD_ALI_DATA2(_dg2, _i2, _i3) \
|
||||
(((_dg2) << 16) | ((_i2) << 8) | (_i3))
|
||||
|
||||
#define VMMC_CMD_ALI_DATA3(_i4, _i5) \
|
||||
(((_i4) << 24) | ((_i5) << 16))
|
||||
|
||||
#define VMMC_CMD_ALM_COEF(_chan, _offset, _len) \
|
||||
(_VMMC_MSG(2, 0, _offset) | _VMMC_CHAN(_chan) | (_len))
|
||||
|
||||
#define CMD_VOICEREC_STATUS_PACKET 0x0
|
||||
#define CMD_VOICEREC_DATA_PACKET 0x1
|
||||
#define CMD_RTP_VOICE_DATA_PACKET 0x4
|
||||
#define CMD_RTP_EVENT_PACKET 0x5
|
||||
#define CMD_ADDRESS_PACKET 0x8
|
||||
#define CMD_FAX_DATA_PACKET 0x10
|
||||
#define CMD_FAX_STATUS_PACKET 0x11
|
||||
#define CMD_P_PHONE_DATA_PACKET 0x12
|
||||
#define CMD_P_PHONE_STATUS_PACKET 0x13
|
||||
|
||||
#define VMMC_CMD_RTP_CFG_US(_chan) \
|
||||
(_VMMC_MSG(6, 3, 17) | _VMMC_CHAN(_chan) | (36))
|
||||
#define VMMC_CMD_RTP_CFG_DS(_chan) \
|
||||
(_VMMC_MSG(6, 3, 25) | _VMMC_CHAN(_chan) | (32))
|
||||
|
||||
#define VMMC_CMD_LEC(_chan) \
|
||||
(_VMMC_MSG(6, 2, 1) | _VMMC_CHAN(_chan) | _VMMC_LENGTH(1))
|
||||
// (_VMMC_MSG(CMD_EOP, ALI_LEC_ECMD, MOD_ALI) | _VMMC_CHAN(_chan) | (32))
|
||||
|
||||
#define VMMC_CMD_LEC_DATA()
|
||||
#endif
|
|
@ -1,221 +0,0 @@
|
|||
#include <linux/kernel.h>
|
||||
|
||||
#include "vmmc.h"
|
||||
#include "vmmc-cmds.h"
|
||||
#include "vmmc-coder.h"
|
||||
#include "vmmc-module.h"
|
||||
#include "mps.h"
|
||||
|
||||
enum vmmc_coder_encoding {
|
||||
VMMC_CODER_ENCODING_ALAW = 2,
|
||||
VMMC_CODER_ENCODING_MLAW = 3,
|
||||
VMMC_CODER_ENCODING_G726_16 = 4,
|
||||
VMMC_CODER_ENCODING_G726_24 = 5,
|
||||
VMMC_CODER_ENCODING_G726_32 = 6,
|
||||
VMMC_CODER_ENCODING_G726_40 = 7,
|
||||
VMMC_CODER_ENCODING_AMR_4_75 = 8,
|
||||
VMMC_CODER_ENCODING_AMR_5_15 = 9,
|
||||
VMMC_CODER_ENCODING_AMR_5_9 = 10,
|
||||
VMMC_CODER_ENCODING_AMR_6_7 = 11,
|
||||
VMMC_CODER_ENCODING_AMR_7_4 = 12,
|
||||
VMMC_CODER_ENCODING_AMR_7_95 = 13,
|
||||
VMMC_CODER_ENCODING_AMR_10_2 = 14,
|
||||
VMMC_CODER_ENCODING_AMR_12_2 = 15,
|
||||
VMMC_CODER_ENCODING_G728_16 = 16,
|
||||
VMMC_CODER_ENCODING_G729AB_8 = 18,
|
||||
VMMC_CODER_ENCODING_G729E_11_8 = 19,
|
||||
VMMC_CODER_ENCODING_G7221_24 = 20,
|
||||
VMMC_CODER_ENCODING_G7221_32 = 21,
|
||||
VMMC_CODER_ENCODING_G722_64 = 22,
|
||||
VMMC_CODER_ENCODING_L16_8 = 24,
|
||||
VMMC_CODER_ENCODING_L16_16 = 25,
|
||||
VMMC_CODER_ENCODING_ILBC_15_2 = 26,
|
||||
VMMC_CODER_ENCODING_ILBC_13_3 = 27,
|
||||
VMMC_CODER_ENCODING_G7231_5_3 = 28,
|
||||
VMMC_CODER_ENCODING_G7231_6_3 = 29,
|
||||
VMMC_CODER_ENCODING_ALAW_VBD = 30,
|
||||
VMMC_CODER_ENCODING_MLAW_VBD = 31,
|
||||
};
|
||||
|
||||
static const uint8_t vmmc_coder_payload_mapping[] = {
|
||||
[VMMC_CODER_ENCODING_ALAW] = 8,
|
||||
[VMMC_CODER_ENCODING_MLAW] = 0,
|
||||
[VMMC_CODER_ENCODING_G726_16] = 35,
|
||||
[VMMC_CODER_ENCODING_G726_24] = 36,
|
||||
[VMMC_CODER_ENCODING_G726_32] = 37,
|
||||
[VMMC_CODER_ENCODING_G726_40] = 38,
|
||||
[VMMC_CODER_ENCODING_AMR_4_75] = 39,
|
||||
[VMMC_CODER_ENCODING_AMR_5_15] = 40,
|
||||
[VMMC_CODER_ENCODING_AMR_5_9] = 41,
|
||||
[VMMC_CODER_ENCODING_AMR_6_7] = 42,
|
||||
[VMMC_CODER_ENCODING_AMR_7_4] = 43,
|
||||
[VMMC_CODER_ENCODING_AMR_7_95] = 44,
|
||||
[VMMC_CODER_ENCODING_AMR_10_2] = 45,
|
||||
[VMMC_CODER_ENCODING_AMR_12_2] = 46,
|
||||
[VMMC_CODER_ENCODING_G728_16] = 47,
|
||||
[VMMC_CODER_ENCODING_G729AB_8] = 48,
|
||||
[VMMC_CODER_ENCODING_G729E_11_8] = 49,
|
||||
[VMMC_CODER_ENCODING_G7221_24] = 50,
|
||||
[VMMC_CODER_ENCODING_G7221_32] = 51,
|
||||
[VMMC_CODER_ENCODING_G722_64] = 52,
|
||||
[VMMC_CODER_ENCODING_L16_8] = 11,
|
||||
[VMMC_CODER_ENCODING_L16_16] = 10,
|
||||
[VMMC_CODER_ENCODING_ILBC_15_2] = 53,
|
||||
[VMMC_CODER_ENCODING_ILBC_13_3] = 54,
|
||||
[VMMC_CODER_ENCODING_G7231_5_3] = 4,
|
||||
[VMMC_CODER_ENCODING_G7231_6_3] = 4,
|
||||
[VMMC_CODER_ENCODING_ALAW_VBD] = 55,
|
||||
[VMMC_CODER_ENCODING_MLAW_VBD] = 56,
|
||||
};
|
||||
|
||||
static uint32_t payload_enc[9];
|
||||
static uint32_t payload_dec[8];
|
||||
|
||||
static inline struct vmmc_coder *vmmc_module_to_coder(struct vmmc_module *module)
|
||||
{
|
||||
return container_of(module, struct vmmc_coder, module);
|
||||
}
|
||||
|
||||
static int vmmc_coder_enable(struct vmmc_module *module, bool enable)
|
||||
{
|
||||
struct vmmc_coder *coder = vmmc_module_to_coder(module);
|
||||
|
||||
coder->enabled = enable;
|
||||
|
||||
/* coder->cmd_cache[0] = VMMC_CMD_CODER_DATA1(coder->enabled, 0, 0, 0, coder->id,
|
||||
module->pins[0], 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
return vmmc_command_write(coder->vmmc, VMMC_CMD_CODER(coder->id),
|
||||
coder->cmd_cache);*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vmmc_coder_sync(struct vmmc_module *module)
|
||||
{
|
||||
struct vmmc_coder *coder = vmmc_module_to_coder(module);
|
||||
|
||||
coder->cmd_cache[0] = VMMC_CMD_CODER_DATA1(coder->enabled, 0, 1, 1, coder->id,
|
||||
module->pins[0], 1, 1, 1, 1, 1, 1, 0, 0, 0, VMMC_CODER_ENCODING_MLAW);
|
||||
coder->cmd_cache[1] = VMMC_CMD_CODER_DATA2(0x2000, 0x2000);
|
||||
coder->cmd_cache[2] = VMMC_CMD_CODER_DATA3(0, 0, module->pins[1], 0,
|
||||
module->pins[2], 0, module->pins[3], module->pins[4]);
|
||||
|
||||
return vmmc_command_write(coder->vmmc, VMMC_CMD_CODER(coder->id), coder->cmd_cache);
|
||||
}
|
||||
|
||||
static const struct vmmc_module_ops vmmc_coder_module_ops = {
|
||||
.sync = vmmc_coder_sync,
|
||||
.enable = vmmc_coder_enable,
|
||||
};
|
||||
|
||||
#define VMMC_CMD_CODER_JB(_chan) (_VMMC_MSG(6, 3, 18) | _VMMC_CHAN(_chan) | 8)
|
||||
#define VMMC_CMD_CODER_JB_DATA1(_sf, _prp, _pje, _dvf, _nam, _rad, _adap, _init_pod) \
|
||||
(((_sf) << 31) | ((_prp) << 23) | ((_pje) << 22) | ((_dvf) << 21) | \
|
||||
((_nam) << 20) | ((_rad) << 17) | ((_adap) << 16) | (_init_pod))
|
||||
#define VMMC_CMD_CODER_JB_DATA2(_min_pod, _max_pod) \
|
||||
(((_min_pod) << 16) | (_max_pod))
|
||||
#define VMMC_CMD_CODER_JB_DATA3(_adap_factor, _min_margin, _mode) \
|
||||
(((_adap_factor) << 24) | ((_min_margin) << 16) | (_mode))
|
||||
|
||||
int vmmc_coder_init(struct vmmc_coder *coder, struct vmmc *vmmc, unsigned int id)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = vmmc_module_init(&coder->module, 5, &vmmc_coder_module_ops);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
coder->id = id;
|
||||
coder->module.id = id + 0x18;
|
||||
coder->vmmc = vmmc;
|
||||
coder->enabled = 0;
|
||||
|
||||
coder->cmd_cache[0] = VMMC_CMD_CODER_DATA1(0, 0, 0, 0, id, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
coder->cmd_cache[1] = VMMC_CMD_CODER_DATA2(0, 0);
|
||||
coder->cmd_cache[2] = VMMC_CMD_CODER_DATA3(0, 0, 0, 0, 0, 0, 0, 0);
|
||||
coder->cmd_cache[3] = VMMC_CMD_CODER_DATA4(0);
|
||||
|
||||
coder->jitter_buffer_cache[0] = VMMC_CMD_CODER_JB_DATA1(0x16, 1, 0, 0, 1, 1,
|
||||
1, 0x50);
|
||||
coder->jitter_buffer_cache[1] = VMMC_CMD_CODER_JB_DATA2(0x50, 0x05a0);
|
||||
coder->jitter_buffer_cache[2] = VMMC_CMD_CODER_JB_DATA3(0x0d, 0x28, 1);
|
||||
|
||||
vmmc_command_write(coder->vmmc, VMMC_CMD_RTP_CFG_US(coder->id), payload_enc);
|
||||
vmmc_command_write(coder->vmmc, VMMC_CMD_RTP_CFG_DS(coder->id), payload_dec);
|
||||
vmmc_command_write(coder->vmmc, VMMC_CMD_CODER_JB(coder->id),
|
||||
coder->jitter_buffer_cache);
|
||||
vmmc_command_write(coder->vmmc, VMMC_CMD_CODER(coder->id), coder->cmd_cache);
|
||||
|
||||
vmmc_register_module(vmmc, &coder->module);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void vmmc_coder_event(struct vmmc *vmmc, unsigned int chan, unsigned int type)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
void vmmc_coder_event(struct vmmc_coder *coder, unsigned int len)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
provide_mem_region(coder->vmmc, vmmc_coder_alloc_paket(coder)->head, 512);
|
||||
|
||||
skb = skb_dequeue(&coder->paket_queue);
|
||||
skb_put(skb, len);
|
||||
|
||||
tapi_stream_recv(&coder->vmmc->tdev, skb);
|
||||
}
|
||||
*/
|
||||
/*
|
||||
int vmmc_coder_set_codec(struct vmmc_coder *coder, enum vmmc_codec codec)
|
||||
{
|
||||
}*/
|
||||
|
||||
void vmmc_init_coders(struct vmmc *vmmc)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
payload_enc[0] = 0;
|
||||
payload_enc[1] = 0x0;
|
||||
payload_enc[1] |= vmmc_coder_payload_mapping[2] << 8;
|
||||
payload_enc[1] |= vmmc_coder_payload_mapping[3] << 8;
|
||||
for (i = 2; i < 9; ++i) {
|
||||
payload_enc[i] = vmmc_coder_payload_mapping[i*4 - 4] << 24;
|
||||
payload_enc[i] |= vmmc_coder_payload_mapping[i*4 - 3] << 16;
|
||||
payload_enc[i] |= vmmc_coder_payload_mapping[i*4 - 2] << 8;
|
||||
payload_enc[i] |= vmmc_coder_payload_mapping[i*4 - 1];
|
||||
payload_enc[i] |= 0x80808080;
|
||||
}
|
||||
for (i = 0; i < 7; ++i) {
|
||||
payload_dec[i] = vmmc_coder_payload_mapping[i*4 + 2] << 24;
|
||||
payload_dec[i] |= vmmc_coder_payload_mapping[i*4 + 3] << 16;
|
||||
payload_dec[i] |= vmmc_coder_payload_mapping[i*4 + 4] << 8;
|
||||
payload_dec[i] |= vmmc_coder_payload_mapping[i*4 + 5];
|
||||
}
|
||||
payload_dec[i] = vmmc_coder_payload_mapping[i*4 + 2] << 24;
|
||||
payload_dec[i] |= vmmc_coder_payload_mapping[i*4 + 3] << 16;
|
||||
|
||||
|
||||
vmmc->num_coders = 5;
|
||||
vmmc->coder = kcalloc(sizeof(*vmmc->coder), vmmc->num_coders, GFP_KERNEL);
|
||||
|
||||
for (i = 0; i < vmmc->num_coders; ++i)
|
||||
vmmc_coder_init(&vmmc->coder[i], vmmc, i);
|
||||
}
|
||||
|
||||
struct vmmc_coder *vmmc_coder_get(struct vmmc *vmmc)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < vmmc->num_coders; ++i) {
|
||||
if (!test_and_set_bit(i, &vmmc->coder_used))
|
||||
return &vmmc->coder[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void vmmc_coder_put(struct vmmc *vmmc, struct vmmc_coder *coder)
|
||||
{
|
||||
clear_bit(coder->id, &vmmc->coder_used);
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
|
||||
struct vmmc_coder {
|
||||
struct vmmc *vmmc;
|
||||
unsigned int id;
|
||||
|
||||
struct vmmc_module module;
|
||||
|
||||
unsigned int enabled;
|
||||
|
||||
uint32_t cmd_cache[4];
|
||||
uint32_t jitter_buffer_cache[3];
|
||||
|
||||
struct tapi_stream *stream;
|
||||
};
|
|
@ -1,646 +0,0 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <linux/firmware.h>
|
||||
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <ifxmips_gptu.h>
|
||||
|
||||
#include <linux/tapi/tapi.h>
|
||||
|
||||
#include "vmmc.h"
|
||||
#include "mps.h"
|
||||
#include "mps-msg.h"
|
||||
#include "mps-irq.h"
|
||||
#include "vmmc-cmds.h"
|
||||
|
||||
#include "vmmc-port.h"
|
||||
#include "vmmc-stream.h"
|
||||
#include "vmmc-link.h"
|
||||
#include "vmmc-coder.h"
|
||||
|
||||
struct vmmc_capabilities {
|
||||
uint8_t num_alm;
|
||||
uint8_t num_pcm;
|
||||
uint8_t num_signal;
|
||||
uint8_t num_coder;
|
||||
uint8_t num_agc;
|
||||
uint8_t num_eq;
|
||||
uint8_t num_nlec;
|
||||
uint8_t num_wlec;
|
||||
uint8_t num_nwlec;
|
||||
uint8_t num_wwlec;
|
||||
uint8_t num_tone_generators;
|
||||
uint8_t num_dtmf_generators;
|
||||
uint8_t num_caller_id_senders;
|
||||
uint8_t num_caller_id_recivers;
|
||||
};
|
||||
|
||||
#define MPS_FIRMWARE_MAGIC 0xcc123456
|
||||
|
||||
struct vmmc_firmware_head {
|
||||
uint32_t crc;
|
||||
uint32_t crc_start_addr;
|
||||
uint32_t crc_end_addr;
|
||||
uint32_t version;
|
||||
uint32_t encrypted;
|
||||
uint32_t magic;
|
||||
uint32_t mem;
|
||||
} __packed;
|
||||
|
||||
#define VMMC_FIFO_UPSTREAM_CMD_BASE_ADDR 0x00
|
||||
#define VMMC_FIFO_UPSTREAM_CMD_SIZE_ADDR 0x04
|
||||
#define VMMC_FIFO_DOWNSTREAM_CMD_BASE_ADDR 0x08
|
||||
#define VMMC_FIFO_DOWNSTREAM_CMD_SIZE_ADDR 0x0c
|
||||
#define VMMC_FIFO_UPSTREAM_DATA_BASE_ADDR 0x10
|
||||
#define VMMC_FIFO_UPSTREAM_DATA_SIZE_ADDR 0x14
|
||||
#define VMMC_FIFO_DOWNSTREAM_DATA_BASE_ADDR 0x18
|
||||
#define VMMC_FIFO_DOWNSTREAM_DATA_SIZE_ADDR 0x1c
|
||||
#define VMMC_FIFO_UPSTREAM_CMD_TAIL_ADDR 0x20
|
||||
#define VMMC_FIFO_UPSTREAM_CMD_HEAD_ADDR 0x24
|
||||
#define VMMC_FIFO_DOWNSTREAM_CMD_TAIL_ADDR 0x28
|
||||
#define VMMC_FIFO_DOWNSTREAM_CMD_HEAD_ADDR 0x2c
|
||||
#define VMMC_FIFO_UPSTREAM_DATA_TAIL_ADDR 0x30
|
||||
#define VMMC_FIFO_UPSTREAM_DATA_HEAD_ADDR 0x34
|
||||
#define VMMC_FIFO_DOWNSTREAM_DATA_TAIL_ADDR 0x38
|
||||
#define VMMC_FIFO_DOWNSTREAM_DATA_HEAD_ADDR 0x3c
|
||||
|
||||
#define VMMC_FIFO_EVENT_BASE_ADDR 0x180
|
||||
#define VMMC_FIFO_EVENT_SIZE_ADDR 0x184
|
||||
#define VMMC_FIFO_EVENT_TAIL_ADDR 0x188
|
||||
#define VMMC_FIFO_EVENT_HEAD_ADDR 0x18c
|
||||
|
||||
|
||||
/* Calculates the base of the fifo behind the given fifo */
|
||||
#define VMMC_NEXT_FIFO_BASE0(_fifo) \
|
||||
(VMMC_FIFO_ ## _fifo ## _BASE + VMMC_FIFO_ ## _fifo ## _SIZE)
|
||||
#define VMMC_NEXT_FIFO_BASE1(_fifo) \
|
||||
(VMMC_FIFO_ ## _fifo ## _BASE + VMMC_FIFO_ ## _fifo ## _SIZE)
|
||||
#define VMMC_NEXT_FIFO_BASE2(_fifo) \
|
||||
(VMMC_FIFO_ ## _fifo ## _BASE + VMMC_FIFO_ ## _fifo ## _SIZE)
|
||||
|
||||
/* Fifo sizes */
|
||||
#define VMMC_FIFO_UPSTREAM_CMD_SIZE 64
|
||||
#define VMMC_FIFO_DOWNSTREAM_CMD_SIZE 64
|
||||
#define VMMC_FIFO_UPSTREAM_DATA_SIZE 64
|
||||
#define VMMC_FIFO_DOWNSTREAM_DATA_SIZE 128
|
||||
#define VMMC_FIFO_EVENT_SIZE 64
|
||||
|
||||
/* Fifo addresses */
|
||||
#define VMMC_FIFO_UPSTREAM_CMD_BASE 0x40
|
||||
#define VMMC_FIFO_DOWNSTREAM_CMD_BASE VMMC_NEXT_FIFO_BASE0(UPSTREAM_CMD)
|
||||
#define VMMC_FIFO_UPSTREAM_DATA_BASE VMMC_NEXT_FIFO_BASE1(DOWNSTREAM_CMD)
|
||||
#define VMMC_FIFO_DOWNSTREAM_DATA_BASE VMMC_NEXT_FIFO_BASE2(UPSTREAM_DATA)
|
||||
#define VMMC_FIFO_EVENT_BASE 0x190
|
||||
|
||||
#define VMMC_DECLARE_FIFO_CONFIG(_name, _fifo) \
|
||||
static const struct mps_fifo_config _name = { \
|
||||
.tail_addr = VMMC_FIFO_ ## _fifo ## _TAIL_ADDR, \
|
||||
.head_addr = VMMC_FIFO_ ## _fifo ## _HEAD_ADDR, \
|
||||
.base_addr = VMMC_FIFO_ ## _fifo ## _BASE_ADDR, \
|
||||
.size_addr = VMMC_FIFO_ ## _fifo ## _SIZE_ADDR, \
|
||||
.base = VMMC_FIFO_ ## _fifo ## _BASE, \
|
||||
.size = VMMC_FIFO_ ## _fifo ## _SIZE, \
|
||||
}
|
||||
|
||||
VMMC_DECLARE_FIFO_CONFIG(vmmc_fifo_config_upstream_cmd, UPSTREAM_CMD);
|
||||
VMMC_DECLARE_FIFO_CONFIG(vmmc_fifo_config_downstream_cmd, DOWNSTREAM_CMD);
|
||||
VMMC_DECLARE_FIFO_CONFIG(vmmc_fifo_config_upstream_data, UPSTREAM_DATA);
|
||||
VMMC_DECLARE_FIFO_CONFIG(vmmc_fifo_config_downstream_data, DOWNSTREAM_DATA);
|
||||
VMMC_DECLARE_FIFO_CONFIG(vmmc_fifo_config_event, EVENT);
|
||||
|
||||
static void vmmc_setup_fifos(struct vmmc *vmmc)
|
||||
{
|
||||
mps_configure_mailbox(vmmc->mps, &vmmc->mbox_cmd,
|
||||
&vmmc_fifo_config_upstream_cmd, &vmmc_fifo_config_downstream_cmd);
|
||||
mps_configure_mailbox(vmmc->mps, &vmmc->mbox_data,
|
||||
&vmmc_fifo_config_upstream_data, &vmmc_fifo_config_downstream_data);
|
||||
|
||||
mps_configure_fifo(vmmc->mps, &vmmc->fifo_event, &vmmc_fifo_config_event);
|
||||
}
|
||||
|
||||
static uint32_t cram_data[] = {
|
||||
0x00200000, 0x00008e59, 0x165235cd, 0x17e2f141, 0xe3eef301, 0x0a431281,
|
||||
0x04fdf20d, 0x7fe363d5, 0xfd4b7333, 0x7ffffd44, 0xfcf80298, 0xfecd00c9,
|
||||
0xff900042, 0xfff70003, 0x000923b7, 0xe92a354d, 0xc8981f44, 0x9c0f1257,
|
||||
0x26aacf33, 0x27db9836, 0x10586f5b, 0x9c167d2d, 0x94b679a7, 0x8c227660,
|
||||
0x83fa7491, 0x7ce0826a, 0x7ff87ff4, 0x296b4e22, 0x76e67fff, 0x008ffc04,
|
||||
0x02cbfb36, 0x026afeba, 0x009effc3, 0x0013fffd, 0x23b7e92a, 0x354dc898,
|
||||
0x1f449c0f, 0x125726aa, 0xcf3327db, 0x98361058, 0x74bc93d6, 0x7ebc8f61,
|
||||
0x7d068986, 0x7b46833b, 0x7a3b7f00, 0x287a47b1, 0x05800367, 0x20ae2715,
|
||||
0x0fb5da12, 0x1935f53b, 0x01230240, 0xfc717f00, 0x2000d346,
|
||||
};
|
||||
|
||||
static void vmmc_push_data_paket(struct vmmc *vmmc, int type, unsigned int chan,
|
||||
void __iomem *addr, size_t len)
|
||||
{
|
||||
uint32_t data[3];
|
||||
|
||||
data[0] = VMMC_VOICE_DATA(type, chan, 8);
|
||||
data[1] = CPHYSADDR(addr);
|
||||
data[2] = len;
|
||||
|
||||
mps_fifo_in(&vmmc->mbox_data.downstream, data, 3);
|
||||
}
|
||||
|
||||
static struct sk_buff *vmmc_alloc_data_paket(struct vmmc *vmmc)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = alloc_skb(512, GFP_KERNEL);
|
||||
|
||||
skb_queue_tail(&vmmc->recv_queue, skb);
|
||||
|
||||
return skb;
|
||||
}
|
||||
|
||||
static void vmmc_provide_paket(struct vmmc *vmmc)
|
||||
{
|
||||
struct sk_buff *skb = vmmc_alloc_data_paket(vmmc);
|
||||
vmmc_push_data_paket(vmmc, CMD_ADDRESS_PACKET, 0, skb->data, skb->len);
|
||||
}
|
||||
|
||||
static void vmmc_recv_paket(struct vmmc *vmmc, unsigned int chan, void __iomem *addr, size_t len)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct sk_buff *tmp;
|
||||
|
||||
skb_queue_walk_safe(&vmmc->recv_queue, skb, tmp) {
|
||||
if (skb->data == addr)
|
||||
break;
|
||||
}
|
||||
|
||||
if (skb == (struct sk_buff *)(&vmmc->recv_queue)) {
|
||||
printk("AHHHH\n");
|
||||
return;
|
||||
}
|
||||
|
||||
dma_cache_inv((u32)addr, len);
|
||||
skb_unlink(skb, &vmmc->recv_queue);
|
||||
|
||||
if (!vmmc->coder[chan].stream) {
|
||||
kfree_skb(skb);
|
||||
return;
|
||||
}
|
||||
|
||||
skb_put(skb, len);
|
||||
tapi_stream_recv(&vmmc->tdev, vmmc->coder[chan].stream, skb);
|
||||
}
|
||||
|
||||
void vmmc_send_paket(struct vmmc *vmmc, unsigned int chan, struct sk_buff *skb)
|
||||
{
|
||||
skb_queue_tail(&vmmc->send_queue, skb);
|
||||
|
||||
dma_cache_wback((u32)skb->data, skb->len);
|
||||
vmmc_push_data_paket(vmmc, CMD_RTP_VOICE_DATA_PACKET, chan, skb->data,
|
||||
skb->len);
|
||||
}
|
||||
|
||||
static void vmmc_free_paket(struct vmmc *vmmc, void __iomem *addr, size_t len)
|
||||
{
|
||||
struct sk_buff *skb;
|
||||
struct sk_buff *tmp;
|
||||
|
||||
skb_queue_walk_safe(&vmmc->send_queue, skb, tmp) {
|
||||
if (skb->data == addr)
|
||||
break;
|
||||
}
|
||||
|
||||
if (skb == (struct sk_buff *)(&vmmc->send_queue)) {
|
||||
printk("AHHHH\n");
|
||||
} else {
|
||||
skb_unlink(skb, &vmmc->send_queue);
|
||||
kfree_skb(skb);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void vmmc_write_cram_data(struct vmmc *vmmc, unsigned int id,
|
||||
uint32_t *data, size_t length)
|
||||
{
|
||||
size_t transfer_length;
|
||||
size_t offset = 0;
|
||||
uint32_t cmd;
|
||||
|
||||
length *= 4;
|
||||
offset = 0x5;
|
||||
|
||||
while (length) {
|
||||
transfer_length = length > 56 ? 56 : length;
|
||||
cmd = VMMC_CMD_ALM_COEF(id, offset, transfer_length);
|
||||
vmmc_command_write(vmmc, cmd, data);
|
||||
|
||||
data += transfer_length >> 2;
|
||||
offset += transfer_length >> 1;
|
||||
length -= transfer_length;
|
||||
}
|
||||
}
|
||||
|
||||
int vmmc_command_read(struct vmmc *vmmc, uint32_t cmd, uint32_t *result)
|
||||
{
|
||||
struct mps_mailbox *mbox = &vmmc->mbox_cmd;
|
||||
|
||||
INIT_COMPLETION(vmmc->cmd_completion);
|
||||
|
||||
mps_fifo_in(&mbox->downstream, &cmd, 1);
|
||||
|
||||
wait_for_completion(&vmmc->cmd_completion);
|
||||
|
||||
mps_fifo_out(&mbox->upstream, result, 1);
|
||||
mps_fifo_out(&mbox->upstream, result, (*result & 0xff) / 4);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vmmc_command_write(struct vmmc *vmmc, uint32_t cmd,
|
||||
const uint32_t *data)
|
||||
{
|
||||
struct mps_mailbox *mbox = &vmmc->mbox_cmd;
|
||||
/* int i;
|
||||
|
||||
printk("cmd: %x\n", cmd);
|
||||
for (i = 0; i < DIV_ROUND_UP((cmd & 0xff), 4); ++i) {
|
||||
printk("data[%d] = %x\n", i, data[i]);
|
||||
}
|
||||
*/
|
||||
while (mps_fifo_len(&mbox->downstream) < (cmd & 0xff) + 4)
|
||||
mdelay(100);
|
||||
|
||||
mps_fifo_in(&mbox->downstream, &cmd, 1);
|
||||
mps_fifo_in(&mbox->downstream, data, DIV_ROUND_UP((cmd & 0xff), 4));
|
||||
|
||||
mdelay(100);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int vmmc_modules_sync(struct tapi_device *tapi)
|
||||
{
|
||||
struct vmmc *vmmc = tdev_to_vmmc(tapi);
|
||||
struct vmmc_module *module;
|
||||
|
||||
list_for_each_entry(module, &vmmc->modules, head)
|
||||
vmmc_module_sync(module);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct tapi_ops vmmc_tapi_ops = {
|
||||
.send_dtmf_event = vmmc_port_send_dtmf_event,
|
||||
.ring = vmmc_port_ring,
|
||||
|
||||
.sync = vmmc_modules_sync,
|
||||
|
||||
.stream_alloc = vmmc_stream_alloc,
|
||||
.stream_free = vmmc_stream_free,
|
||||
.stream_send = vmmc_stream_send,
|
||||
|
||||
.link_alloc = vmmc_tapi_link_alloc,
|
||||
.link_free = vmmc_tapi_link_free,
|
||||
.link_enable = vmmc_tapi_link_enable,
|
||||
.link_disable = vmmc_tapi_link_disable,
|
||||
};
|
||||
|
||||
static void setup_alm(struct vmmc *vmmc)
|
||||
{
|
||||
int i;
|
||||
|
||||
vmmc->tdev.ports = kcalloc(2, sizeof(*vmmc->tdev.ports), GFP_KERNEL);
|
||||
vmmc->ports = kcalloc(2, sizeof(*vmmc->ports), GFP_KERNEL);
|
||||
|
||||
for (i = 0; i < 2; ++i)
|
||||
vmmc_port_init(vmmc, &vmmc->ports[i], &vmmc->tdev.ports[i], i);
|
||||
|
||||
skb_queue_head_init(&vmmc->send_queue);
|
||||
skb_queue_head_init(&vmmc->recv_queue);
|
||||
|
||||
for (i = 0; i < 10; ++i)
|
||||
vmmc_provide_paket(vmmc);
|
||||
|
||||
vmmc->tdev.num_ports = 2;
|
||||
vmmc->tdev.ops = &vmmc_tapi_ops;
|
||||
tapi_device_register(&vmmc->tdev, "vmmc", vmmc->dev);
|
||||
}
|
||||
|
||||
static void vmmc_init_timer(struct vmmc *vmmc)
|
||||
{
|
||||
unsigned int timer;
|
||||
unsigned int timer_flags;
|
||||
int ret;
|
||||
unsigned long loops, count;
|
||||
|
||||
timer = TIMER1B;
|
||||
|
||||
timer_flags =
|
||||
TIMER_FLAG_16BIT | TIMER_FLAG_COUNTER | TIMER_FLAG_CYCLIC |
|
||||
TIMER_FLAG_DOWN | TIMER_FLAG_FALL_EDGE | TIMER_FLAG_SYNC |
|
||||
TIMER_FLAG_CALLBACK_IN_IRQ;
|
||||
ret = ifxmips_request_timer (timer, timer_flags, 1, 0, 0);
|
||||
if (ret < 0) {
|
||||
printk("FAILED TO INIT TIMER\n");
|
||||
return;
|
||||
}
|
||||
ret = ifxmips_start_timer (timer, 0);
|
||||
if (ret < 0) {
|
||||
printk("FAILED TO START TIMER\n");
|
||||
return;
|
||||
}
|
||||
do
|
||||
{
|
||||
loops++;
|
||||
ifxmips_get_count_value(timer, &count);
|
||||
} while (count);
|
||||
|
||||
*((volatile uint32_t *) (KSEG1 + 0x1e100a00 + 0x0014)) = 0x000005c5;
|
||||
}
|
||||
|
||||
static void vmmc_free_timer(struct vmmc *vmmc)
|
||||
{
|
||||
ifxmips_free_timer(TIMER1B);
|
||||
}
|
||||
|
||||
static void vmmc_get_capabilities(struct vmmc *vmmc)
|
||||
{
|
||||
uint32_t data[10];
|
||||
uint8_t len;
|
||||
|
||||
vmmc_command_read(vmmc,
|
||||
MPS_MSG_CMD_EOP_SYSTEM(SYS_CAP_ECMD, sizeof(uint32_t)), data);
|
||||
|
||||
len = ((data[0] >> 16) & 0xff) - sizeof(uint32_t);
|
||||
|
||||
if (len > sizeof(data))
|
||||
len = sizeof(data);
|
||||
|
||||
vmmc_command_read(vmmc,
|
||||
MPS_MSG_CMD_EOP_SYSTEM(SYS_CAP_ECMD, len), data);
|
||||
|
||||
len /= 4;
|
||||
|
||||
/* for (;len > 0; --len) {
|
||||
printk("fw cap(%d): %.2x\n", 10-len, data[10-len]);
|
||||
}
|
||||
*/
|
||||
setup_alm(vmmc);
|
||||
}
|
||||
|
||||
static void vmmc_get_firmware_version(struct vmmc *vmmc)
|
||||
{
|
||||
uint32_t data[1];
|
||||
|
||||
vmmc_command_read(vmmc, MPS_CMD_GET_VERSION, data);
|
||||
|
||||
printk("firmware version: %x\n", *data);
|
||||
|
||||
vmmc_get_capabilities(vmmc);
|
||||
}
|
||||
|
||||
static irqreturn_t vmmc_firmware_loaded_irq(int irq, void *devid)
|
||||
{
|
||||
struct vmmc *vmmc = devid;
|
||||
complete(&vmmc->firmware_loaded_completion);
|
||||
printk("Firmware loaded irq\n");
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t vmmc_cmd_error_irq(int irq, void *devid)
|
||||
{
|
||||
/* struct vmmc *vmmc = devid;*/
|
||||
|
||||
printk("cmd error!!!!\n");
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t vmmc_recv_ov_irq(int irq, void *devid)
|
||||
{
|
||||
struct vmmc *vmmc = devid;
|
||||
uint32_t data[2] = {
|
||||
VMMC_CMD_SERR_ACK(0),
|
||||
VMMC_CMD_SERR_ACK_DATA1(1)
|
||||
};
|
||||
uint32_t voice_data[64];
|
||||
|
||||
return IRQ_HANDLED;
|
||||
|
||||
mps_fifo_in(&vmmc->mbox_cmd.downstream, data, 2);
|
||||
mps_fifo_out(&vmmc->mbox_data.upstream, voice_data, 15);
|
||||
|
||||
printk("recv overflow: %x\n", voice_data[0]);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t vmmc_event_fifo_irq(int irq, void *devid)
|
||||
{
|
||||
struct vmmc *vmmc = devid;
|
||||
uint32_t event, event_id;
|
||||
uint32_t data = 0;
|
||||
unsigned int chan;
|
||||
|
||||
mps_fifo_out(&vmmc->fifo_event, &event, 1);
|
||||
|
||||
event_id = event & VMMC_EVENT_ID_MASK;
|
||||
chan = VMMC_MSG_GET_CHAN(event);
|
||||
|
||||
if (event & 0xff)
|
||||
mps_fifo_out(&vmmc->fifo_event, &data, 1);
|
||||
|
||||
switch (event_id) {
|
||||
case VMMC_EVENT_HOOK_ID:
|
||||
vmmc_alm_hook_event_handler(vmmc, chan, data);
|
||||
break;
|
||||
case VMMC_EVENT_DTMF_ID:
|
||||
vmmc_sig_dtmf_event_handler(vmmc, chan, data);
|
||||
break;
|
||||
default:
|
||||
printk("Ein unbekanntes Event: %x %x\n", event, data);
|
||||
break;
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t vmmc_mbox_data_irq_handler(int irq, void *devid)
|
||||
{
|
||||
struct vmmc *vmmc = devid;
|
||||
struct mps_mailbox *mbox = &vmmc->mbox_data;
|
||||
unsigned int count, type, chan;
|
||||
uint32_t data[2];
|
||||
void __iomem *addr;
|
||||
size_t len;
|
||||
|
||||
mps_fifo_out(&mbox->upstream, data, 1);
|
||||
|
||||
count = (data[0] & 0xff) / 8;
|
||||
type = (data[0] >> 24) & 0xff;
|
||||
chan = (data[0] >> 16) & 0xff;
|
||||
|
||||
while (count) {
|
||||
mps_fifo_out(&mbox->upstream, data, 2);
|
||||
|
||||
addr = (void __iomem *)CKSEG0ADDR(data[0]);
|
||||
len = data[1];
|
||||
|
||||
switch (type) {
|
||||
case CMD_ADDRESS_PACKET:
|
||||
vmmc_free_paket(vmmc, addr, len);
|
||||
break;
|
||||
case CMD_RTP_VOICE_DATA_PACKET:
|
||||
vmmc_provide_paket(vmmc);
|
||||
vmmc_recv_paket(vmmc, chan, addr, len);
|
||||
break;
|
||||
}
|
||||
--count;
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static irqreturn_t vmmc_mbox_cmd_irq_handler(int irq, void *devid)
|
||||
{
|
||||
struct vmmc *vmmc = devid;
|
||||
|
||||
complete(&vmmc->cmd_completion);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static void vmmc_load_firmware(const struct firmware *fw, void *context)
|
||||
{
|
||||
struct vmmc *vmmc = context;
|
||||
struct vmmc_firmware_head *fw_head;
|
||||
size_t tail_size;
|
||||
enum mps_boot_config config;
|
||||
|
||||
if (!fw) {
|
||||
printk("failed to load tapi firmware\n");
|
||||
// request_firmware_nowait(THIS_MODULE, 1, "danube_firmware.bin", vmmc->dev,
|
||||
// GFP_KERNEL, vmmc, vmmc_load_firmware);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fw->size < sizeof(*fw_head))
|
||||
return;
|
||||
|
||||
fw_head = (struct vmmc_firmware_head *)((uint8_t *)fw->data + fw->size - sizeof(*fw_head));
|
||||
|
||||
if (fw_head->magic != MPS_FIRMWARE_MAGIC) {
|
||||
config = MPS_BOOT_LEGACY;
|
||||
tail_size = sizeof(uint32_t);
|
||||
} else {
|
||||
config = MPS_BOOT_ENCRYPTED;
|
||||
tail_size = sizeof(*fw_head) - sizeof(uint32_t);
|
||||
}
|
||||
|
||||
vmmc_setup_fifos(vmmc);
|
||||
init_completion(&vmmc->firmware_loaded_completion);
|
||||
mps_load_firmware(vmmc->mps, fw->data, fw->size - tail_size, config);
|
||||
wait_for_completion_timeout(&vmmc->firmware_loaded_completion, 5*HZ);
|
||||
vmmc_init_timer(vmmc);
|
||||
vmmc_write_cram_data(vmmc, 0, cram_data, ARRAY_SIZE(cram_data));
|
||||
vmmc_write_cram_data(vmmc, 1, cram_data, ARRAY_SIZE(cram_data));
|
||||
vmmc_get_firmware_version(vmmc);
|
||||
vmmc_init_coders(vmmc);
|
||||
}
|
||||
|
||||
static int vmmc_request_irqs(struct vmmc *vmmc)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = request_irq(vmmc->irq_fw_loaded, vmmc_firmware_loaded_irq, 0, "vmmc fw loaded", vmmc);
|
||||
ret = request_irq(vmmc->irq_event_fifo, vmmc_event_fifo_irq, 0, "vmmc event fifo", vmmc);
|
||||
ret = request_irq(vmmc->irq_cmd_error, vmmc_cmd_error_irq, 0,
|
||||
"cmd error irq", vmmc);
|
||||
ret = request_irq(MPS_IRQ_RCV_OVERFLOW, vmmc_recv_ov_irq, 0,
|
||||
"recv_ov irq", vmmc);
|
||||
|
||||
ret = request_irq(vmmc->irq_mbox_cmd, vmmc_mbox_cmd_irq_handler, 0,
|
||||
"vmmc cmd mailbox irq", vmmc);
|
||||
|
||||
ret = request_irq(vmmc->irq_mbox_data, vmmc_mbox_data_irq_handler, 0,
|
||||
"vmmc data mailbox irq", vmmc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devinit vmmc_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct vmmc *vmmc;
|
||||
int ret = 0;
|
||||
|
||||
vmmc = kzalloc(sizeof(*vmmc), GFP_KERNEL);
|
||||
|
||||
if (!vmmc)
|
||||
return -ENOMEM;
|
||||
|
||||
vmmc->dev = &pdev->dev;
|
||||
vmmc->mps = device_to_mps(pdev->dev.parent);
|
||||
|
||||
if (!vmmc->mps) {
|
||||
goto err_free;
|
||||
ret = -EBUSY;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&vmmc->modules);
|
||||
init_completion(&vmmc->cmd_completion);
|
||||
|
||||
vmmc->irq_fw_loaded = MPS_IRQ_DOWNLOAD_DONE;
|
||||
vmmc->irq_mbox_cmd = MPS_IRQ_CMD_UPSTREAM;
|
||||
vmmc->irq_mbox_data = MPS_IRQ_DATA_UPSTREAM;
|
||||
vmmc->irq_event_fifo = MPS_IRQ_EVENT;
|
||||
vmmc->irq_cmd_error = MPS_IRQ_CMD_ERROR;
|
||||
|
||||
platform_set_drvdata(pdev, vmmc);
|
||||
|
||||
vmmc_request_irqs(vmmc);
|
||||
|
||||
request_firmware_nowait(THIS_MODULE, 1, "danube_firmware.bin", &pdev->dev,
|
||||
GFP_KERNEL, vmmc, vmmc_load_firmware);
|
||||
|
||||
return 0;
|
||||
|
||||
err_free:
|
||||
kfree(vmmc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit vmmc_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct vmmc *vmmc = platform_get_drvdata(pdev);
|
||||
vmmc_free_timer(vmmc);
|
||||
|
||||
tapi_device_unregister(&vmmc->tdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct platform_driver vmmc_driver = {
|
||||
.probe = vmmc_probe,
|
||||
.remove = __devexit_p(vmmc_remove),
|
||||
.driver = {
|
||||
.name = "vmmc",
|
||||
.owner = THIS_MODULE
|
||||
},
|
||||
};
|
||||
|
||||
static int __init vmmc_init(void)
|
||||
{
|
||||
return platform_driver_register(&vmmc_driver);
|
||||
}
|
||||
module_init(vmmc_init);
|
||||
|
||||
static void __exit vmmc_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&vmmc_driver);
|
||||
}
|
||||
module_exit(vmmc_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
|
|
@ -1,52 +0,0 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/tapi/tapi.h>
|
||||
|
||||
#include "vmmc-link.h"
|
||||
#include "vmmc-module.h"
|
||||
|
||||
struct vmmc_tapi_link {
|
||||
struct tapi_link tapi_link;
|
||||
struct vmmc_link vmmc_link;
|
||||
};
|
||||
|
||||
struct tapi_link *vmmc_tapi_link_alloc(struct tapi_device *tdev,
|
||||
struct tapi_endpoint *ep1, struct tapi_endpoint *ep2)
|
||||
{
|
||||
struct vmmc_tapi_link *link = kzalloc(sizeof(*link), GFP_KERNEL);
|
||||
struct vmmc_module *module1 = tapi_endpoint_to_vmmc_module(ep1);
|
||||
struct vmmc_module *module2 = tapi_endpoint_to_vmmc_module(ep2);
|
||||
|
||||
vmmc_link_init(&link->vmmc_link, module1, module2);
|
||||
|
||||
return &link->tapi_link;
|
||||
}
|
||||
|
||||
void vmmc_tapi_link_free(struct tapi_device *tdev, struct tapi_link *tapi_link)
|
||||
{
|
||||
struct vmmc_tapi_link *link = container_of(tapi_link, struct vmmc_tapi_link,
|
||||
tapi_link);
|
||||
|
||||
vmmc_link_put(&link->vmmc_link);
|
||||
kfree(link);
|
||||
}
|
||||
|
||||
int vmmc_tapi_link_enable(struct tapi_device *tdev,
|
||||
struct tapi_link *tapi_link)
|
||||
{
|
||||
struct vmmc_tapi_link *link = container_of(tapi_link, struct vmmc_tapi_link,
|
||||
tapi_link);
|
||||
|
||||
vmmc_link_enable(&link->vmmc_link);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vmmc_tapi_link_disable(struct tapi_device *tdev,
|
||||
struct tapi_link *tapi_link)
|
||||
{
|
||||
struct vmmc_tapi_link *link = container_of(tapi_link, struct vmmc_tapi_link,
|
||||
tapi_link);
|
||||
|
||||
vmmc_link_disable(&link->vmmc_link);
|
||||
return 0;
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
#ifndef __VMMC_LINK_H__
|
||||
#define __VMMC_LINK_H__
|
||||
|
||||
struct tapi_link *vmmc_tapi_link_alloc(struct tapi_device *tdev,
|
||||
struct tapi_endpoint *ep1, struct tapi_endpoint *ep2);
|
||||
void vmmc_tapi_link_free(struct tapi_device *tdev, struct tapi_link *link);
|
||||
int vmmc_tapi_link_enable(struct tapi_device *tdev, struct tapi_link *link);
|
||||
int vmmc_tapi_link_disable(struct tapi_device *tdev, struct tapi_link *link);
|
||||
|
||||
#endif
|
|
@ -1,130 +0,0 @@
|
|||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
#include <asm/bitops.h>
|
||||
|
||||
#include "vmmc-module.h"
|
||||
|
||||
int vmmc_module_init(struct vmmc_module *module, size_t num_pins,
|
||||
const struct vmmc_module_ops *ops)
|
||||
{
|
||||
module->pins = kcalloc(num_pins, sizeof(*module->pins), GFP_KERNEL);
|
||||
|
||||
if (!module->pins)
|
||||
return -ENOMEM;
|
||||
|
||||
module->num_pins = num_pins;
|
||||
module->ops = ops;
|
||||
|
||||
mutex_init(&module->lock);
|
||||
module->refcount = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vmmc_module_sync(struct vmmc_module *module)
|
||||
{
|
||||
if (!test_and_clear_bit(VMMC_MODULE_FLAG_MODIFIED, &module->flags))
|
||||
return 0;
|
||||
|
||||
return module->ops->sync(module);
|
||||
}
|
||||
|
||||
int vmmc_module_get_pin(struct vmmc_module *module)
|
||||
{
|
||||
size_t i = 0;
|
||||
int ret = 0;
|
||||
|
||||
for (i = 0; i < module->num_pins; ++i) {
|
||||
if (!test_and_set_bit(VMMC_MODULE_FLAG_PIN_USED(i), &module->flags))
|
||||
break;
|
||||
}
|
||||
if (i == module->num_pins)
|
||||
ret = -EBUSY;
|
||||
else
|
||||
ret = i;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void vmmc_module_put_pin(struct vmmc_module *module, unsigned int pin)
|
||||
{
|
||||
module->pins[pin] = 0;
|
||||
clear_bit(VMMC_MODULE_FLAG_PIN_USED(pin), &module->flags);
|
||||
}
|
||||
|
||||
void vmmc_module_set_pin_input(struct vmmc_module *module, unsigned int pin,
|
||||
struct vmmc_module *input)
|
||||
{
|
||||
if (input)
|
||||
module->pins[pin] = input->id;
|
||||
else
|
||||
module->pins[pin] = 0;
|
||||
|
||||
set_bit(VMMC_MODULE_FLAG_MODIFIED, &module->flags);
|
||||
}
|
||||
|
||||
static void vmmc_module_enable(struct vmmc_module *module)
|
||||
{
|
||||
mutex_lock(&module->lock);
|
||||
|
||||
if (++module->refcount == 1)
|
||||
module->ops->enable(module, true);
|
||||
|
||||
mutex_unlock(&module->lock);
|
||||
}
|
||||
|
||||
static void vmmc_module_disable(struct vmmc_module *module)
|
||||
{
|
||||
mutex_lock(&module->lock);
|
||||
|
||||
if (module->refcount <= 0)
|
||||
printk(KERN_ERR "vmmc module: unbalanced disable\n");
|
||||
else if (--module->refcount == 0)
|
||||
module->ops->enable(module, false);
|
||||
|
||||
mutex_unlock(&module->lock);
|
||||
}
|
||||
|
||||
|
||||
unsigned int vmmc_link_init(struct vmmc_link *link,
|
||||
struct vmmc_module *a, struct vmmc_module *b)
|
||||
{
|
||||
link->pins[0] = vmmc_module_get_pin(a);
|
||||
link->pins[1] = vmmc_module_get_pin(b);
|
||||
link->modules[0] = a;
|
||||
link->modules[1] = b;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void vmmc_link_put(struct vmmc_link *link)
|
||||
{
|
||||
vmmc_link_disable(link);
|
||||
vmmc_module_sync(link->modules[0]);
|
||||
vmmc_module_sync(link->modules[1]);
|
||||
vmmc_module_put_pin(link->modules[0], link->pins[0]);
|
||||
vmmc_module_put_pin(link->modules[1], link->pins[1]);
|
||||
}
|
||||
|
||||
void vmmc_link_enable(struct vmmc_link *link)
|
||||
{
|
||||
vmmc_module_set_pin_input(link->modules[0], link->pins[0],
|
||||
link->modules[1]);
|
||||
vmmc_module_set_pin_input(link->modules[1], link->pins[1],
|
||||
link->modules[0]);
|
||||
|
||||
vmmc_module_enable(link->modules[0]);
|
||||
vmmc_module_enable(link->modules[1]);
|
||||
}
|
||||
|
||||
void vmmc_link_disable(struct vmmc_link *link)
|
||||
{
|
||||
vmmc_module_set_pin_input(link->modules[0], link->pins[0], NULL);
|
||||
vmmc_module_set_pin_input(link->modules[1], link->pins[1], NULL);
|
||||
|
||||
vmmc_module_disable(link->modules[0]);
|
||||
vmmc_module_disable(link->modules[1]);
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
#ifndef __VMMC_MODULE_H__
|
||||
#define __VMMC_MODULE_H__
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/tapi/tapi.h>
|
||||
|
||||
struct vmmc_module;
|
||||
|
||||
struct vmmc_module_ops {
|
||||
int (*sync)(struct vmmc_module *);
|
||||
int (*enable)(struct vmmc_module *, bool enable);
|
||||
};
|
||||
|
||||
struct vmmc_module
|
||||
{
|
||||
unsigned int id;
|
||||
|
||||
size_t num_pins;
|
||||
unsigned int *pins;
|
||||
|
||||
const struct vmmc_module_ops *ops;
|
||||
|
||||
unsigned long flags;
|
||||
#define VMMC_MODULE_FLAG_PIN_USED(x) (x)
|
||||
#define VMMC_MODULE_FLAG_MODIFIED 31
|
||||
struct mutex lock;
|
||||
struct list_head head;
|
||||
|
||||
unsigned int refcount;
|
||||
};
|
||||
|
||||
int vmmc_module_init(struct vmmc_module *module, size_t num_pins,
|
||||
const struct vmmc_module_ops *ops);
|
||||
int vmmc_module_sync(struct vmmc_module *module);
|
||||
|
||||
struct vmmc_link {
|
||||
struct vmmc_module *modules[2];
|
||||
unsigned int pins[2];
|
||||
};
|
||||
|
||||
struct vmmc_endpoint {
|
||||
struct tapi_endpoint ep;
|
||||
struct vmmc_module *module;
|
||||
};
|
||||
|
||||
void vmmc_link_enable(struct vmmc_link *link);
|
||||
void vmmc_link_disable(struct vmmc_link *link);
|
||||
unsigned int vmmc_link_init(struct vmmc_link *link,
|
||||
struct vmmc_module *a, struct vmmc_module *b);
|
||||
void vmmc_link_put(struct vmmc_link *link);
|
||||
|
||||
int vmmc_module_get_pin(struct vmmc_module *module);
|
||||
void vmmc_module_put_pin(struct vmmc_module *module, unsigned int pin);
|
||||
void vmmc_module_set_pin_input(struct vmmc_module *module, unsigned int pin,
|
||||
struct vmmc_module *input);
|
||||
|
||||
|
||||
static inline struct vmmc_module *tapi_endpoint_to_vmmc_module(struct tapi_endpoint *ep)
|
||||
{
|
||||
return tapi_endpoint_get_data(ep);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,48 +0,0 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <linux/tapi/tapi.h>
|
||||
|
||||
#include "vmmc.h"
|
||||
#include "vmmc-port.h"
|
||||
#include "vmmc-alm.h"
|
||||
#include "vmmc-sig.h"
|
||||
|
||||
int vmmc_port_ring(struct tapi_device *tdev, struct tapi_port *port, bool ring)
|
||||
{
|
||||
struct vmmc *vmmc = tdev_to_vmmc(tdev);
|
||||
|
||||
return vmmc_alm_set_state(&vmmc->ports[port->id].alm,
|
||||
ring ? VMMC_ALM_STATE_RING : VMMC_ALM_STATE_ONHOOK);
|
||||
}
|
||||
|
||||
int vmmc_port_send_dtmf_event(struct tapi_device *tdev,
|
||||
struct tapi_port *port, struct tapi_dtmf_event *event)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct vmmc_port *vmmc_port_init(struct vmmc *vmmc, struct vmmc_port *port,
|
||||
struct tapi_port *tport, unsigned int id)
|
||||
{
|
||||
vmmc_alm_init(&port->alm, vmmc, id);
|
||||
vmmc_sig_init(&port->sig, vmmc, id);
|
||||
|
||||
port->sig_pin = vmmc_module_get_pin(&port->sig.module);
|
||||
vmmc_module_set_pin_input(&port->sig.module, port->sig_pin,
|
||||
&port->alm.module);
|
||||
|
||||
vmmc_module_sync(&port->sig.module);
|
||||
|
||||
vmmc_alm_set_state(&port->alm, VMMC_ALM_STATE_ONHOOK);
|
||||
|
||||
tport->id = id;
|
||||
tapi_endpoint_set_data(&tport->ep, &port->alm.module);
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
void vmmc_port_put(struct vmmc *vmmc, struct vmmc_port *port)
|
||||
{
|
||||
vmmc_module_put_pin(&port->sig.module, port->sig_pin);
|
||||
}
|
|
@ -1,22 +0,0 @@
|
|||
#ifndef __VMMC_PORT_H__
|
||||
#define __VMMC_PORT_H__
|
||||
|
||||
#include "vmmc-alm.h"
|
||||
#include "vmmc-sig.h"
|
||||
|
||||
void vmmc_port_free(struct vmmc *vmmc, struct vmmc_port *port);
|
||||
|
||||
int vmmc_port_ring(struct tapi_device *tdev, struct tapi_port *port, bool ring);
|
||||
int vmmc_port_send_dtmf_event(struct tapi_device *tdev,
|
||||
struct tapi_port *port, struct tapi_dtmf_event *event);
|
||||
struct vmmc_port *vmmc_port_init(struct vmmc *vmmc, struct vmmc_port *port,
|
||||
struct tapi_port *tport, unsigned int id);
|
||||
|
||||
struct vmmc_port
|
||||
{
|
||||
struct vmmc_alm alm;
|
||||
struct vmmc_sig sig;
|
||||
unsigned int sig_pin;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,19 +0,0 @@
|
|||
#ifndef __VMMC_SIG_H__
|
||||
#define __VMMC_SIG_H__
|
||||
|
||||
#include "vmmc-module.h"
|
||||
|
||||
struct vmmc_sig {
|
||||
struct vmmc *vmmc;
|
||||
unsigned int id;
|
||||
struct vmmc_module module;
|
||||
|
||||
uint32_t sig_cache;
|
||||
uint32_t dtmfr_cache;
|
||||
};
|
||||
|
||||
int vmmc_sig_init(struct vmmc_sig *sig, struct vmmc *vmmc, unsigned int id);
|
||||
|
||||
void vmmc_sig_dtmf_event_handler(struct vmmc *vmmc, uint32_t event, uint32_t data);
|
||||
|
||||
#endif
|
|
@ -1,69 +0,0 @@
|
|||
#include <linux/kernel.h>
|
||||
|
||||
#include "vmmc.h"
|
||||
#include "vmmc-sig.h"
|
||||
#include "vmmc-cmds.h"
|
||||
|
||||
static struct vmmc_sig *vmmc_module_to_sig(struct vmmc_module *module)
|
||||
{
|
||||
return container_of(module, struct vmmc_sig, module);
|
||||
}
|
||||
|
||||
static int vmmc_sig_enable(struct vmmc_module *module, bool enabled)
|
||||
{
|
||||
struct vmmc_sig *sig = vmmc_module_to_sig(module);
|
||||
|
||||
return 0;
|
||||
|
||||
sig->sig_cache = VMMC_CMD_SIG_SET_ENABLE(sig->sig_cache, enabled);
|
||||
|
||||
return vmmc_command_write(sig->vmmc, VMMC_CMD_SIG(sig->id), &sig->sig_cache);
|
||||
}
|
||||
|
||||
static int vmmc_sig_sync(struct vmmc_module *module)
|
||||
{
|
||||
struct vmmc_sig *sig = vmmc_module_to_sig(module);
|
||||
|
||||
sig->sig_cache = VMMC_CMD_SIG_SET_INPUTS(sig->sig_cache,
|
||||
module->pins[0], module->pins[1]);
|
||||
|
||||
vmmc_command_write(sig->vmmc, VMMC_CMD_SIG(sig->id),
|
||||
&sig->sig_cache);
|
||||
|
||||
return vmmc_command_write(sig->vmmc, VMMC_CMD_DTMFR(sig->id),
|
||||
&sig->dtmfr_cache);
|
||||
}
|
||||
|
||||
static const struct vmmc_module_ops vmmc_sig_ops = {
|
||||
.enable = vmmc_sig_enable,
|
||||
.sync = vmmc_sig_sync,
|
||||
};
|
||||
|
||||
int vmmc_sig_init(struct vmmc_sig *sig, struct vmmc *vmmc, unsigned int id)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = vmmc_module_init(&sig->module, 2, &vmmc_sig_ops);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
sig->id = id;
|
||||
sig->module.id = id + 0x1e;
|
||||
sig->vmmc = vmmc;
|
||||
sig->sig_cache = VMMC_CMD_SIG_DATA(1, 1, 0, 0, 0, 0, 0);
|
||||
sig->dtmfr_cache = VMMC_CMD_DTMFR_DATA(1, 1, id);
|
||||
|
||||
vmmc_register_module(vmmc, &sig->module);
|
||||
|
||||
vmmc_command_write(sig->vmmc, VMMC_CMD_SIG(sig->id),
|
||||
&sig->sig_cache);
|
||||
vmmc_command_write(sig->vmmc, VMMC_CMD_DTMFR(sig->id),
|
||||
&sig->dtmfr_cache);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void vmmc_sig_dtmf_event_handler(struct vmmc *vmmc, uint32_t id, uint32_t data)
|
||||
{
|
||||
tapi_report_dtmf_event(&vmmc->tdev, &vmmc->tdev.ports[id], data & 0xf);
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/tapi/tapi.h>
|
||||
#include <linux/skbuff.h>
|
||||
|
||||
#include "vmmc.h"
|
||||
#include "vmmc-coder.h"
|
||||
|
||||
struct vmmc_tapi_stream {
|
||||
struct vmmc_coder *coder;
|
||||
struct tapi_stream stream;
|
||||
};
|
||||
|
||||
struct vmmc_tapi_stream *tapi_to_vmmc_stream(struct tapi_stream * stream)
|
||||
{
|
||||
return container_of(stream, struct vmmc_tapi_stream, stream);
|
||||
}
|
||||
|
||||
struct tapi_stream *vmmc_stream_alloc(struct tapi_device *tdev)
|
||||
{
|
||||
struct vmmc *vmmc = tdev_to_vmmc(tdev);
|
||||
struct vmmc_tapi_stream *stream;
|
||||
struct vmmc_coder *coder;
|
||||
|
||||
coder = vmmc_coder_get(vmmc);
|
||||
if (!coder)
|
||||
return ERR_PTR(-ENODEV);
|
||||
|
||||
stream = kzalloc(sizeof(*stream), GFP_KERNEL);
|
||||
if (!stream)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
stream->coder = coder;
|
||||
coder->stream = &stream->stream;
|
||||
tapi_endpoint_set_data(&stream->stream.ep, &coder->module);
|
||||
|
||||
return &stream->stream;
|
||||
}
|
||||
|
||||
void vmmc_stream_free(struct tapi_device *tdev, struct tapi_stream *tstream)
|
||||
{
|
||||
struct vmmc *vmmc = tdev_to_vmmc(tdev);
|
||||
struct vmmc_tapi_stream *stream = tapi_to_vmmc_stream(tstream);
|
||||
|
||||
stream->coder->stream = NULL;
|
||||
|
||||
vmmc_coder_put(vmmc, stream->coder);
|
||||
kfree(stream);
|
||||
}
|
||||
|
||||
int vmmc_stream_start(struct tapi_device *tdev, struct tapi_stream *stream)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vmmc_stream_stop(struct tapi_device *tdev, struct tapi_stream *stream)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vmmc_stream_send(struct tapi_device *tdev, struct tapi_stream *stream,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
struct vmmc *vmmc = tdev_to_vmmc(tdev);
|
||||
struct vmmc_coder *coder = tapi_to_vmmc_stream(stream)->coder;
|
||||
|
||||
vmmc_send_paket(vmmc, coder->id, skb);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
int vmmc_stream_recv(struct vmmc_stream *stream)
|
||||
{
|
||||
tapi_stream_recv(&stream->coder->vmmc->tdev stream->stream, skb);
|
||||
}*/
|
|
@ -1,10 +0,0 @@
|
|||
#ifndef __VMMC_STREAM_H__
|
||||
#define __VMMC_STREAM_H__
|
||||
|
||||
struct tapi_stream *vmmc_stream_alloc(struct tapi_device *tdev);
|
||||
void vmmc_stream_free(struct tapi_device *tdev, struct tapi_stream *stream);
|
||||
int vmmc_stream_start(struct tapi_device *tdev, struct tapi_stream *stream);
|
||||
int vmmc_stream_send(struct tapi_device *tdev, struct tapi_stream *stream,
|
||||
struct sk_buff *skb);
|
||||
|
||||
#endif
|
|
@ -1,90 +0,0 @@
|
|||
static uint32_t magic_init[] = {
|
||||
/* ALI INIT */
|
||||
/*0x0601210c, 0x88002000, 0x20000000, 0x00000000, 0xffffffff,*/
|
||||
/* COD_CHAN_SPEECH_ECMD */
|
||||
/*0x06016110, 0x2462f700, 0x20002000, 0x00000000, 0x00000000, 0xffffffff,*/
|
||||
/* COD_DEC_STAT_ECMD */
|
||||
/*0x06017504, 0x00c00000, 0xffffffff,*/
|
||||
/* COD_JB_CONF_ECMD */
|
||||
/*0x06017208, 0x16410050, 0x005005a0, 0xffffffff,*/
|
||||
/* SIG_RTP_SUP */
|
||||
/*0x0601500c, 0x00000000, 0x00000060, 0x0712007f, 0xffffffff,*/
|
||||
/* SIG_CHAN */
|
||||
/*0x06014104, 0xc0190000, 0xffffffff,*/
|
||||
/* SIG_CIDS_CTRL_ECMD */
|
||||
/*0x06014204, 0x3811e000, 0xffffffff, */
|
||||
/* SIG_DTMFATG_DATA */
|
||||
/*0x06014b04, 0x00010000, 0xffffffff,*/
|
||||
/* SIG_DTMFATG_CTRL */
|
||||
/*0x06014304, 0x6a110000, 0xffffffff,
|
||||
0x0601cc04, 0xe21c2000, 0xffffffff,
|
||||
0x06014404, 0xb0110000, 0xffffffff,
|
||||
0x06014a04, 0x04510000, 0xffffffff,
|
||||
0x06014604, 0x04560000, 0xffffffff,
|
||||
0x06014104, 0xc0190000, 0xffffffff,*/
|
||||
/* COD_CHAN_RTP_SUP_CFG_USD */
|
||||
/*0x06017124, 0x00000000, 0x00008880, 0xe3e4e5e6, 0x72727272, 0x72727272,
|
||||
0x0f7f1261, 0x7374097f, 0xf1f06767, 0x04047675, 0xffffffff,*/
|
||||
/* COD_CHAN_RTP_SUP_CFG_DS */
|
||||
/* 0x06017920, 0x08006364, 0x65667272, 0x72727272, 0x72720f7f, 0x12617374,
|
||||
0x097f7170, 0x67670404, 0x76750000, 0xffffffff, */
|
||||
/* OPMODE_CMD */
|
||||
0x01010004, 0x00010000, 0xffffffff,
|
||||
0x01000004, 0x00030000, 0xffffffff,
|
||||
/*0x01010004, 0x00010000, 0xffffffff,*/
|
||||
/* COD_CHAN_RTP_SUP_CFG_US */
|
||||
/* 0x06017124, 0x00000000, 0x00008880, 0xe3e4e5e6, 0x72727272, 0x72727272,
|
||||
0x0f7f1261, 0x7374097f, 0xf1f06767, 0x04047675, 0xffffffff, */
|
||||
/* COD_CHAN_RTP_SUP_CFG_DS */
|
||||
/* 0x06017920, 0x08006364, 0x65667272, 0x72727272, 0x72720f7f, 0x12617374,
|
||||
0x097f7170, 0x67670404, 0x76750000, 0xffffffff, */
|
||||
/* COD_JB_CONF */
|
||||
/* 0x06017208, 0x16410050, 0x005005a0, 0xffffffff, */
|
||||
/* COD_CHAN_RTP_SUP_CFG_US */
|
||||
/*0x06017108, 0x00000000, 0x00008880, 0xffffffff,*/
|
||||
/* COD_CHAN_RTP_TIMESTAMP */
|
||||
/*0x06017004, 0x00000000, 0xffffffff,*/
|
||||
/* SIG_RTP_SUP */
|
||||
/* 0x0601500c, 0x00000000, 0x00000062, 0x0712007f, 0xffffffff,*/
|
||||
/* SIG_DTMFR_CTRL */
|
||||
/*0x06014404, 0xb0010000, 0xffffffff,*/
|
||||
/* COD_CHAN_SPEECH */
|
||||
/* 0x06016110, 0x0462d600, 0x20002000, 0x00000000, 0x00000000, 0xffffffff, */
|
||||
/* ALI_CHAN */
|
||||
0x0601210c, 0x88232000, 0x20000000, 0x00000000, 0xffffffff,
|
||||
/* SIG_CHAN */
|
||||
/*0x06014104, 0xc5190000, 0xffffffff,*/
|
||||
/* SIG_DTMFR_CTRL_ECMD */
|
||||
/*0x06014404, 0x30010000, 0xffffffff,*/
|
||||
/* SIG_CHAN_ECMD */
|
||||
/*0x06014104, 0x45190000, 0xffffffff,*/
|
||||
};
|
||||
|
||||
static void setup_alm(struct mps *mps, int chan)
|
||||
{
|
||||
uint32_t *data = magic_init;
|
||||
int size, i;
|
||||
|
||||
/* data[0] = ALI_CHAN_DATA1(1, 0, 0, 1, 1, 0, 0);
|
||||
data[1] = ALI_CHAN_DATA2(0, 0, 0);
|
||||
data[2] = ALI_CHAN_DATA3(0, 0);*/
|
||||
|
||||
size = 1;
|
||||
for (i = 1; i < ARRAY_SIZE(magic_init); ++i) {
|
||||
if (magic_init[i] == 0xffffffff) {
|
||||
|
||||
printk("cmd: %x\n", *data);
|
||||
VMMC_FIFO_fifo_in(&mps->mbox_cmd.downstream, data, size);
|
||||
size = 0;
|
||||
data = &magic_init[i+1];
|
||||
mdelay(500);
|
||||
} else {
|
||||
size += 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* VMMC_FIFO_mailbox_command_write(&mps->mbox_cmd, MPS_CMD_ALI(chan), data);*/
|
||||
}
|
||||
|
||||
|
|
@ -1,68 +0,0 @@
|
|||
#ifndef __VMMC_H__
|
||||
|
||||
#include <linux/list.h>
|
||||
#include <linux/tapi/tapi.h>
|
||||
|
||||
#include "mps.h"
|
||||
#include "vmmc-module.h"
|
||||
|
||||
struct vmmc
|
||||
{
|
||||
struct mps *mps;
|
||||
struct device *dev;
|
||||
|
||||
struct vmmc_port *ports;
|
||||
|
||||
struct completion firmware_loaded_completion;
|
||||
struct completion cmd_completion;
|
||||
|
||||
struct mps_mailbox mbox_cmd;
|
||||
struct mps_mailbox mbox_data;
|
||||
struct mps_fifo fifo_event;
|
||||
|
||||
int irq_fw_loaded;
|
||||
int irq_mbox_cmd;
|
||||
int irq_mbox_data;
|
||||
int irq_event_fifo;
|
||||
int irq_cmd_error;
|
||||
|
||||
unsigned int num_coders;
|
||||
struct vmmc_coder *coder;
|
||||
unsigned long coder_used;
|
||||
|
||||
struct list_head modules;
|
||||
|
||||
struct tapi_device tdev;
|
||||
|
||||
struct sk_buff_head recv_queue;
|
||||
struct sk_buff_head send_queue;
|
||||
};
|
||||
|
||||
static inline struct vmmc *tdev_to_vmmc(struct tapi_device *tdev)
|
||||
{
|
||||
return container_of(tdev, struct vmmc, tdev);
|
||||
}
|
||||
|
||||
static inline void vmmc_register_module(struct vmmc *vmmc,
|
||||
struct vmmc_module *module)
|
||||
{
|
||||
list_add_tail(&module->head, &vmmc->modules);
|
||||
}
|
||||
|
||||
static inline void vmmc_unregister_module(struct vmmc *vmmc,
|
||||
struct vmmc_module *module)
|
||||
{
|
||||
list_del(&module->head);
|
||||
}
|
||||
|
||||
int vmmc_command_write(struct vmmc *vmmc, uint32_t cmd,
|
||||
const uint32_t *data);
|
||||
int vmmc_command_read(struct vmmc *vmmc, uint32_t cmd, uint32_t *result);
|
||||
|
||||
struct vmmc_coder *vmmc_coder_get(struct vmmc *);
|
||||
void vmmc_coder_put(struct vmmc *, struct vmmc_coder *);
|
||||
void vmmc_init_coders(struct vmmc *);
|
||||
|
||||
void vmmc_send_paket(struct vmmc *vmmc, unsigned int chan, struct sk_buff *skb);
|
||||
|
||||
#endif
|
|
@ -1,7 +0,0 @@
|
|||
|
||||
tapi-objs := tapi-core.o tapi-port.o tapi-input.o
|
||||
tapi-objs += tapi-control.o
|
||||
tapi-objs += tapi-stream.o
|
||||
tapi-objs += tapi-sysfs-port.o
|
||||
|
||||
obj-m += tapi.o
|
|
@ -1,193 +0,0 @@
|
|||
#include <linux/cdev.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <linux/tapi/tapi.h>
|
||||
#include <linux/tapi/tapi-ioctl.h>
|
||||
|
||||
/* FIXME Does it acutally make sense to allow more then one application at a
|
||||
* time to open the control device? For example calling sync from one app will
|
||||
* also sync all others. */
|
||||
|
||||
struct tapi_control_file {
|
||||
struct tapi_device *tdev;
|
||||
struct list_head links;
|
||||
};
|
||||
|
||||
static struct tapi_endpoint *tapi_lookup_endpoint(struct tapi_device *tdev,
|
||||
unsigned int ep_id)
|
||||
{
|
||||
struct tapi_stream *stream;
|
||||
|
||||
if (ep_id < tdev->num_ports)
|
||||
return &tdev->ports[ep_id].ep;
|
||||
|
||||
list_for_each_entry(stream, &tdev->streams, head) {
|
||||
if (stream->ep.id == ep_id)
|
||||
return &stream->ep;
|
||||
}
|
||||
|
||||
return ERR_PTR(-ENOENT);
|
||||
}
|
||||
|
||||
static inline struct tapi_device *inode_to_tdev(struct inode *inode)
|
||||
{
|
||||
return container_of(inode->i_cdev, struct tapi_char_device, cdev)->tdev;
|
||||
}
|
||||
|
||||
static int tapi_control_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
int ret;
|
||||
struct tapi_device *tdev = inode_to_tdev(inode);
|
||||
struct tapi_control_file *tctrl;
|
||||
|
||||
get_device(&tdev->dev);
|
||||
|
||||
tctrl = kzalloc(sizeof(*tctrl), GFP_KERNEL);
|
||||
if (!tctrl) {
|
||||
ret = -ENOMEM;
|
||||
goto err_put_device;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&tctrl->links);
|
||||
tctrl->tdev = tdev;
|
||||
|
||||
file->private_data = tctrl;
|
||||
|
||||
return 0;
|
||||
|
||||
err_put_device:
|
||||
put_device(&tdev->dev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tapi_control_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct tapi_control_file *tctrl = file->private_data;
|
||||
struct tapi_link *link;
|
||||
|
||||
if (tctrl) {
|
||||
list_for_each_entry(link, &tctrl->links, head)
|
||||
tapi_link_free(tctrl->tdev, link);
|
||||
|
||||
put_device(&tctrl->tdev->dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long tapi_control_ioctl_link_alloc(struct tapi_control_file *tctrl,
|
||||
unsigned long arg)
|
||||
{
|
||||
struct tapi_link *link;
|
||||
struct tapi_endpoint *ep1, *ep2;
|
||||
|
||||
ep1 = tapi_lookup_endpoint(tctrl->tdev, arg >> 16);
|
||||
ep2 = tapi_lookup_endpoint(tctrl->tdev, arg & 0xffff);
|
||||
|
||||
link = tapi_link_alloc(tctrl->tdev, ep1, ep2);
|
||||
if (IS_ERR(link))
|
||||
return PTR_ERR(link);
|
||||
|
||||
list_add_tail(&link->head, &tctrl->links);
|
||||
|
||||
return link->id;
|
||||
}
|
||||
|
||||
struct tapi_link *tapi_control_lookup_link(struct tapi_control_file *tctrl,
|
||||
unsigned int id)
|
||||
{
|
||||
struct tapi_link *link;
|
||||
|
||||
list_for_each_entry(link, &tctrl->links, head) {
|
||||
if (link->id == id)
|
||||
return link;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static long tapi_control_ioctl_link_free(struct tapi_control_file *tctrl,
|
||||
unsigned long arg)
|
||||
{
|
||||
struct tapi_link *link = tapi_control_lookup_link(tctrl, arg);
|
||||
if (!link)
|
||||
return -ENOENT;
|
||||
|
||||
tapi_link_free(tctrl->tdev, link);
|
||||
list_del(&link->head);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long tapi_control_ioctl_link_enable(struct tapi_control_file *tctrl,
|
||||
unsigned long arg)
|
||||
{
|
||||
struct tapi_link *link = tapi_control_lookup_link(tctrl, arg);
|
||||
if (!link)
|
||||
return -ENOENT;
|
||||
|
||||
return tapi_link_enable(tctrl->tdev, link);
|
||||
}
|
||||
|
||||
static long tapi_control_ioctl_link_disable(struct tapi_control_file *tctrl,
|
||||
unsigned long arg)
|
||||
{
|
||||
struct tapi_link *link = tapi_control_lookup_link(tctrl, arg);
|
||||
if (!link)
|
||||
return -ENOENT;
|
||||
|
||||
return tapi_link_disable(tctrl->tdev, link);
|
||||
}
|
||||
|
||||
static long tapi_control_ioctl_sync(struct tapi_control_file *tctrl)
|
||||
{
|
||||
return tapi_sync(tctrl->tdev);
|
||||
}
|
||||
|
||||
static long tapi_control_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
int ret;
|
||||
struct tapi_control_file *tctrl = file->private_data;
|
||||
|
||||
switch (cmd) {
|
||||
case TAPI_CONTROL_IOCTL_LINK_ALLOC:
|
||||
ret = tapi_control_ioctl_link_alloc(tctrl, arg);
|
||||
break;
|
||||
case TAPI_CONTROL_IOCTL_LINK_FREE:
|
||||
ret = tapi_control_ioctl_link_free(tctrl, arg);
|
||||
break;
|
||||
case TAPI_CONTROL_IOCTL_LINK_ENABLE:
|
||||
ret = tapi_control_ioctl_link_enable(tctrl, arg);
|
||||
break;
|
||||
case TAPI_CONTROL_IOCTL_LINK_DISABLE:
|
||||
ret = tapi_control_ioctl_link_disable(tctrl, arg);
|
||||
break;
|
||||
case TAPI_CONTROL_IOCTL_SYNC:
|
||||
ret = tapi_control_ioctl_sync(tctrl);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations tapi_control_file_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = tapi_control_open,
|
||||
.release = tapi_control_release,
|
||||
.unlocked_ioctl = tapi_control_ioctl,
|
||||
};
|
||||
|
||||
int tapi_register_control_device(struct tapi_device* tdev)
|
||||
{
|
||||
dev_set_name(&tdev->control_dev.dev, "tapi%uC", tdev->id);
|
||||
return tapi_char_device_register(tdev, &tdev->control_dev, &tapi_control_file_ops);
|
||||
}
|
|
@ -1,250 +0,0 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/list.h>
|
||||
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/err.h>
|
||||
|
||||
#include <linux/tapi/tapi.h>
|
||||
|
||||
|
||||
void tapi_alloc_input(struct tapi_device *tdev, struct tapi_port *port);
|
||||
int tapi_register_port_device(struct tapi_device* tdev, struct tapi_port *port);
|
||||
int tapi_register_stream_device(struct tapi_device* tdev);
|
||||
int tapi_register_control_device(struct tapi_device* tdev);
|
||||
|
||||
static struct class *tapi_class;
|
||||
static int tapi_major;
|
||||
|
||||
#define TAPI_MAX_MINORS 255
|
||||
|
||||
static bool tapi_minors[TAPI_MAX_MINORS];
|
||||
|
||||
static int tapi_get_free_minor(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < TAPI_MAX_MINORS; ++i) {
|
||||
if (!tapi_minors[i]) {
|
||||
tapi_minors[i] = true;
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
int tapi_port_send_dtmf_events(struct tapi_device *tdev, unsigned int port, struct tapi_dtmf *, size_t num_events, unsigned int dealy)
|
||||
{
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tapi_port_send_dtmf_events);
|
||||
*/
|
||||
|
||||
void tapi_report_hook_event(struct tapi_device *tdev, struct tapi_port *port,
|
||||
bool on)
|
||||
{
|
||||
struct tapi_event event;
|
||||
event.type = TAPI_EVENT_TYPE_HOOK;
|
||||
event.port = port->id;
|
||||
event.hook.on = on;
|
||||
|
||||
tapi_report_event(tdev, &event);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tapi_report_hook_event);
|
||||
|
||||
void tapi_report_dtmf_event(struct tapi_device *tdev, struct tapi_port *port,
|
||||
unsigned char code)
|
||||
{
|
||||
struct tapi_event event;
|
||||
event.type = TAPI_EVENT_TYPE_DTMF;
|
||||
event.port = port->id;
|
||||
event.dtmf.code = code;
|
||||
|
||||
tapi_report_event(tdev, &event);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tapi_report_dtmf_event);
|
||||
|
||||
struct tapi_stream *tapi_stream_alloc(struct tapi_device *tdev)
|
||||
{
|
||||
struct tapi_stream *stream;
|
||||
printk("tdev %p\n", tdev);
|
||||
|
||||
if (!tdev->ops || !tdev->ops->stream_alloc)
|
||||
return ERR_PTR(-ENOSYS);
|
||||
|
||||
stream = tdev->ops->stream_alloc(tdev);
|
||||
printk("stream %p\n", stream);
|
||||
if (IS_ERR(stream))
|
||||
return stream;
|
||||
|
||||
stream->id = atomic_inc_return(&tdev->stream_id) - 1;
|
||||
stream->ep.id = stream->id;
|
||||
|
||||
/* mutex_lock(&tdev->lock);*/
|
||||
list_add_tail(&stream->head, &tdev->streams);
|
||||
/* mutex_unlock(&tdev->lock);*/
|
||||
|
||||
return stream;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tapi_stream_alloc);
|
||||
|
||||
void tapi_stream_free(struct tapi_device *tdev, struct tapi_stream *stream)
|
||||
{
|
||||
mutex_lock(&tdev->lock);
|
||||
list_del(&stream->head);
|
||||
mutex_unlock(&tdev->lock);
|
||||
|
||||
tdev->ops->stream_free(tdev, stream);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tapi_stream_free);
|
||||
|
||||
struct tapi_link *tapi_link_alloc(struct tapi_device *tdev,
|
||||
struct tapi_endpoint *ep1, struct tapi_endpoint *ep2)
|
||||
{
|
||||
struct tapi_link *link;
|
||||
|
||||
if (!tdev->ops || !tdev->ops->link_alloc)
|
||||
return ERR_PTR(-ENOSYS);
|
||||
|
||||
link = tdev->ops->link_alloc(tdev, ep1, ep2);
|
||||
if (IS_ERR(link))
|
||||
return link;
|
||||
|
||||
link->id = atomic_inc_return(&tdev->link_id) - 1;
|
||||
|
||||
/*
|
||||
mutex_lock(&tdev->lock);
|
||||
list_add_tail(&link->head, &tdev->links);
|
||||
mutex_unlock(&tdev->lock);
|
||||
*/
|
||||
return link;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tapi_link_alloc);
|
||||
|
||||
void tapi_link_free(struct tapi_device *tdev, struct tapi_link *link)
|
||||
{
|
||||
/*
|
||||
mutex_lock(&tdev->lock);
|
||||
list_del(&link->head);
|
||||
mutex_unlock(&tdev->lock);
|
||||
*/
|
||||
tdev->ops->link_free(tdev, link);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tapi_link_free);
|
||||
|
||||
int tapi_char_device_register(struct tapi_device *tdev,
|
||||
struct tapi_char_device *tchrdev, const struct file_operations *fops)
|
||||
{
|
||||
int ret;
|
||||
struct device *dev = &tchrdev->dev;
|
||||
dev_t devt;
|
||||
int minor = tapi_get_free_minor();
|
||||
|
||||
devt = MKDEV(tapi_major, minor);
|
||||
|
||||
dev->devt = devt;
|
||||
dev->class = tapi_class;
|
||||
dev->parent = &tdev->dev;
|
||||
|
||||
tchrdev->tdev = tdev;
|
||||
|
||||
cdev_init(&tchrdev->cdev, fops);
|
||||
tchrdev->cdev.owner = THIS_MODULE;
|
||||
ret = cdev_add(&tchrdev->cdev, devt, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = device_register(&tchrdev->dev);
|
||||
if (ret)
|
||||
goto err_cdev_del;
|
||||
|
||||
return 0;
|
||||
|
||||
err_cdev_del:
|
||||
cdev_del(&tchrdev->cdev);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int tapi_device_register(struct tapi_device *tdev, const char *name,
|
||||
struct device *parent)
|
||||
{
|
||||
static atomic_t tapi_device_id = ATOMIC_INIT(0);
|
||||
int ret, i;
|
||||
|
||||
tdev->dev.class = tapi_class;
|
||||
tdev->dev.parent = parent;
|
||||
dev_set_name(&tdev->dev, "%s", name);
|
||||
|
||||
ret = device_register(&tdev->dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
tdev->id = atomic_inc_return(&tapi_device_id) - 1;
|
||||
|
||||
mutex_init(&tdev->lock);
|
||||
INIT_LIST_HEAD(&tdev->streams);
|
||||
INIT_LIST_HEAD(&tdev->links);
|
||||
atomic_set(&tdev->link_id, 0);
|
||||
atomic_set(&tdev->stream_id, tdev->num_ports);
|
||||
|
||||
tapi_register_stream_device(tdev);
|
||||
tapi_register_control_device(tdev);
|
||||
|
||||
for (i = 0; i < tdev->num_ports; ++i) {
|
||||
tapi_port_alloc(tdev, i);
|
||||
tapi_alloc_input(tdev, &tdev->ports[i]);
|
||||
tapi_register_port_device(tdev, &tdev->ports[i]);
|
||||
tdev->ports[i].id = i;
|
||||
tdev->ports[i].ep.id = i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tapi_device_register);
|
||||
|
||||
void tapi_device_unregister(struct tapi_device *tdev)
|
||||
{
|
||||
device_unregister(&tdev->dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tapi_device_unregister);
|
||||
|
||||
static int __init tapi_class_init(void)
|
||||
{
|
||||
int ret;
|
||||
dev_t dev;
|
||||
|
||||
tapi_class = class_create(THIS_MODULE, "tapi");
|
||||
|
||||
if (IS_ERR(tapi_class)) {
|
||||
ret = PTR_ERR(tapi_class);
|
||||
printk(KERN_ERR "tapi: Failed to create device class: %d\n", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = alloc_chrdev_region(&dev, 0, TAPI_MAX_MINORS, "tapi");
|
||||
if (ret) {
|
||||
printk(KERN_ERR "tapi: Failed to allocate chrdev region: %d\n", ret);
|
||||
goto err_class_destory;
|
||||
}
|
||||
tapi_major = MAJOR(dev);
|
||||
|
||||
return 0;
|
||||
err_class_destory:
|
||||
class_destroy(tapi_class);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
subsys_initcall(tapi_class_init);
|
||||
|
||||
static void __exit tapi_class_exit(void)
|
||||
{
|
||||
unregister_chrdev_region(MKDEV(tapi_major, 0), TAPI_MAX_MINORS);
|
||||
class_destroy(tapi_class);
|
||||
}
|
||||
module_exit(tapi_class_exit);
|
||||
|
||||
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
|
||||
MODULE_DESCRIPTION("TAPI class");
|
||||
MODULE_LICENSE("GPL");
|
|
@ -1,99 +0,0 @@
|
|||
|
||||
#include <linux/tapi/tapi.h>
|
||||
|
||||
#include <linux/input.h>
|
||||
|
||||
static unsigned short tapi_keycodes[] = {
|
||||
[0] = KEY_NUMERIC_0,
|
||||
[1] = KEY_NUMERIC_1,
|
||||
[2] = KEY_NUMERIC_2,
|
||||
[3] = KEY_NUMERIC_3,
|
||||
[4] = KEY_NUMERIC_4,
|
||||
[5] = KEY_NUMERIC_5,
|
||||
[6] = KEY_NUMERIC_6,
|
||||
[7] = KEY_NUMERIC_7,
|
||||
[8] = KEY_NUMERIC_8,
|
||||
[9] = KEY_NUMERIC_9,
|
||||
[10] = KEY_NUMERIC_STAR,
|
||||
[11] = KEY_NUMERIC_POUND,
|
||||
[12] = KEY_ENTER,
|
||||
[13] = KEY_ESC,
|
||||
};
|
||||
|
||||
static int tapi_input_event(struct input_dev *input, unsigned int type,
|
||||
unsigned int code, int value)
|
||||
{
|
||||
struct tapi_device *tdev = dev_to_tapi(input->dev.parent);
|
||||
struct tapi_port *port = input_get_drvdata(input);
|
||||
|
||||
|
||||
if (type != EV_SND || code != SND_BELL)
|
||||
return -EINVAL;
|
||||
|
||||
tapi_port_set_ring(tdev, port, value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tapi_alloc_input(struct tapi_device *tdev, struct tapi_port *port)
|
||||
{
|
||||
struct input_dev *input;
|
||||
int i;
|
||||
char *phys;
|
||||
|
||||
input = input_allocate_device();
|
||||
|
||||
phys = kzalloc(sizeof("tapi/input000"), GFP_KERNEL);
|
||||
sprintf(phys, "tapi/input%d", port->id);
|
||||
|
||||
input->name = "tapi";
|
||||
input->phys = phys;
|
||||
input->id.bustype = BUS_HOST;
|
||||
input->dev.parent = &tdev->dev;
|
||||
input->evbit[0] = BIT(EV_KEY) | BIT(EV_SND);
|
||||
input->sndbit[0] = BIT(SND_BELL);
|
||||
|
||||
input->event = tapi_input_event;
|
||||
|
||||
input->keycodesize = sizeof(unsigned short);
|
||||
input->keycodemax = ARRAY_SIZE(tapi_keycodes);
|
||||
input->keycode = tapi_keycodes;
|
||||
|
||||
port->input = input;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(tapi_keycodes); ++i)
|
||||
__set_bit(tapi_keycodes[i], input->keybit);
|
||||
|
||||
input_set_drvdata(input, port);
|
||||
input_register_device(input);
|
||||
}
|
||||
|
||||
void tapi_report_event(struct tapi_device *tdev,
|
||||
struct tapi_event *event)
|
||||
{
|
||||
unsigned short key_code;
|
||||
struct input_dev *input;
|
||||
|
||||
if (!tdev || !tdev->ports)
|
||||
return;
|
||||
|
||||
switch (event->type) {
|
||||
case TAPI_EVENT_TYPE_HOOK:
|
||||
if (event->hook.on)
|
||||
key_code = KEY_ENTER;
|
||||
else
|
||||
key_code = KEY_ESC;
|
||||
break;
|
||||
case TAPI_EVENT_TYPE_DTMF:
|
||||
key_code = tapi_keycodes[event->dtmf.code];
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
input = tdev->ports[event->port].input;
|
||||
input_report_key(input, key_code, 1);
|
||||
input_sync(input);
|
||||
input_report_key(input, key_code, 0);
|
||||
input_sync(input);
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
|
||||
static struct tapi_attr default_port[] = {
|
||||
[PORTS] = {
|
||||
.type = TAPI_TYPE_PORTS,
|
||||
.name = "ports",
|
||||
.description = "foobar",
|
||||
.set = tapi_set_ports,
|
||||
.get = tapi_get_ports,
|
||||
},
|
||||
};
|
||||
|
||||
static const struct nla_policy tapi_policy[] = {
|
||||
[TAPI_ATTR_ID] = { .type = NLA_U32 },
|
||||
[TAPI_ATTR_PORT] = { .type = NLA_U32 },
|
||||
[TAPI_ATTR_ENDPOINT] = { .type = NLA_U32 },
|
||||
[TAPI_ATTR_STREAM] = { .type = NLA_U32 }
|
||||
};
|
||||
|
||||
static const struct nla_policy tapi_port_policy[] = {
|
||||
[TAPI_PORT_ID] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static const struct nla_policy tapi_endpoint_policy[] = {
|
||||
[TAPI_ENDPOINT_ID] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static const struct nla_policy tapi_stream_policy[] = {
|
||||
[TAPI_STREAM_ID] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static struct genl_family tapi_nl_family = {
|
||||
.id = GENL_ID_GENERATE,
|
||||
.name = "tapi",
|
||||
.hdrsize = 0,
|
||||
.version = 1,
|
||||
.maxattr = ARRAY_SIZE(tapi_policy),
|
||||
};
|
||||
|
||||
|
||||
|
||||
static struct genl_ops tapi_nl_ops[] = {
|
||||
TAPI_NL_OP(TAPI_CMD_LIST, list_attr),
|
||||
|
||||
};
|
||||
|
||||
static int __init tapi_nl_init(void)
|
||||
{
|
||||
ret = genl_unregister_family(&tapi_nl_family);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
genl_register_ops(&tapi_nl_family, tapi_nl_ops);
|
||||
|
||||
return 0;
|
||||
}
|
||||
module_init(tapi_nl_init);
|
||||
|
||||
static void __exit tapi_nl_exit(void)
|
||||
{
|
||||
genl_unregister_family(&tapi_nl_family);
|
||||
}
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
#include <linux/cdev.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include <linux/tapi/tapi.h>
|
||||
#include <linux/tapi/tapi-ioctl.h>
|
||||
|
||||
static inline struct tapi_port *tapi_char_device_to_port(struct tapi_char_device *chrdev)
|
||||
{
|
||||
return container_of(chrdev, struct tapi_port, chrdev);
|
||||
}
|
||||
|
||||
static int tapi_port_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct tapi_device *tdev = cdev_to_tapi_char_device(inode->i_cdev)->tdev;
|
||||
|
||||
get_device(&tdev->dev);
|
||||
file->private_data = cdev_to_tapi_char_device(inode->i_cdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tapi_port_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct tapi_device *tdev = cdev_to_tapi_char_device(inode->i_cdev)->tdev;
|
||||
|
||||
put_device(&tdev->dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long tapi_port_ioctl_get_endpoint(struct tapi_device *tdev,
|
||||
struct tapi_port *port, unsigned long arg)
|
||||
{
|
||||
return port->ep.id;
|
||||
}
|
||||
|
||||
static long tapi_port_ioctl_set_ring(struct tapi_device *tdev,
|
||||
struct tapi_port *port, unsigned long arg)
|
||||
{
|
||||
tapi_port_set_ring(tdev, port, arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long tapi_port_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
int ret;
|
||||
struct tapi_char_device *tchrdev = file->private_data;
|
||||
struct tapi_device *tdev = tchrdev->tdev;
|
||||
struct tapi_port *port = tapi_char_device_to_port(tchrdev);
|
||||
|
||||
switch (cmd) {
|
||||
case TAPI_PORT_IOCTL_GET_ENDPOINT:
|
||||
ret = tapi_port_ioctl_get_endpoint(tdev, port, arg);
|
||||
break;
|
||||
case TAPI_PORT_IOCTL_SET_RING:
|
||||
ret = tapi_port_ioctl_set_ring(tdev, port, arg);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations tapi_port_file_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = tapi_port_open,
|
||||
.release = tapi_port_release,
|
||||
.unlocked_ioctl = tapi_port_ioctl,
|
||||
};
|
||||
|
||||
int tapi_register_port_device(struct tapi_device* tdev, struct tapi_port *port)
|
||||
{
|
||||
dev_set_name(&port->chrdev.dev, "tapi%uP%u", tdev->id, port->id);
|
||||
return tapi_char_device_register(tdev, &port->chrdev, &tapi_port_file_ops);
|
||||
}
|
|
@ -1,201 +0,0 @@
|
|||
#include <linux/cdev.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/signal.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/poll.h>
|
||||
|
||||
#include <linux/tapi/tapi.h>
|
||||
#include <linux/tapi/tapi-ioctl.h>
|
||||
|
||||
|
||||
struct tapi_stream_file {
|
||||
struct tapi_device *tdev;
|
||||
struct tapi_stream *stream;
|
||||
};
|
||||
|
||||
static inline struct tapi_device *inode_to_tdev(struct inode *inode)
|
||||
{
|
||||
return container_of(inode->i_cdev, struct tapi_char_device, cdev)->tdev;
|
||||
}
|
||||
|
||||
static int tapi_stream_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
int ret;
|
||||
struct tapi_device *tdev = inode_to_tdev(inode);
|
||||
struct tapi_stream_file *stream;
|
||||
|
||||
get_device(&tdev->dev);
|
||||
|
||||
stream = kzalloc(sizeof(*stream), GFP_KERNEL);
|
||||
if (!stream) {
|
||||
ret = -ENOMEM;
|
||||
goto err_put;
|
||||
}
|
||||
|
||||
stream->stream = tapi_stream_alloc(tdev);
|
||||
if (IS_ERR(stream->stream)) {
|
||||
ret = PTR_ERR(stream->stream);
|
||||
goto err_free;
|
||||
}
|
||||
stream->tdev = tdev;
|
||||
|
||||
init_waitqueue_head(&stream->stream->recv_wait);
|
||||
skb_queue_head_init(&stream->stream->recv_queue);
|
||||
|
||||
file->private_data = stream;
|
||||
|
||||
return 0;
|
||||
|
||||
err_free:
|
||||
kfree(stream);
|
||||
err_put:
|
||||
put_device(&tdev->dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int tapi_stream_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
struct tapi_stream_file *stream = file->private_data;
|
||||
|
||||
if (stream) {
|
||||
tapi_stream_free(stream->tdev, stream->stream);
|
||||
put_device(&stream->tdev->dev);
|
||||
kfree(stream);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long tapi_stream_ioctl(struct file *file, unsigned int cmd,
|
||||
unsigned long arg)
|
||||
{
|
||||
int ret = 0;
|
||||
struct tapi_stream_file *stream = file->private_data;
|
||||
struct tapi_device *tdev = stream->tdev;
|
||||
|
||||
switch (cmd) {
|
||||
case TAPI_STREAM_IOCTL_GET_ENDPOINT:
|
||||
ret = stream->stream->ep.id;
|
||||
break;
|
||||
case TAPI_STREAM_IOCTL_CONFIGURE:
|
||||
break;
|
||||
case TAPI_STREAM_IOCTL_START:
|
||||
ret = tapi_stream_start(tdev, stream->stream);
|
||||
break;
|
||||
case TAPI_STREAM_IOCTL_STOP:
|
||||
ret = tapi_stream_stop(tdev, stream->stream);
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned int tapi_stream_poll(struct file *file, struct poll_table_struct *wait)
|
||||
{
|
||||
struct tapi_stream_file *stream = file->private_data;
|
||||
int ret;
|
||||
|
||||
poll_wait(file, &stream->stream->recv_wait, wait);
|
||||
|
||||
ret = POLLOUT;
|
||||
|
||||
if (!skb_queue_empty(&stream->stream->recv_queue))
|
||||
ret |= POLLIN;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t tapi_stream_read(struct file *file, char __user *buffer,
|
||||
size_t count, loff_t *offset)
|
||||
{
|
||||
struct tapi_stream_file *stream = file->private_data;
|
||||
struct sk_buff *skb;
|
||||
|
||||
skb = skb_dequeue(&stream->stream->recv_queue);
|
||||
if (!skb) {
|
||||
if (file->f_flags & O_NONBLOCK)
|
||||
return -EAGAIN;
|
||||
|
||||
do {
|
||||
interruptible_sleep_on(&stream->stream->recv_wait);
|
||||
skb = skb_dequeue(&stream->stream->recv_queue);
|
||||
} while (skb == NULL && !signal_pending(current));
|
||||
|
||||
if (skb == NULL)
|
||||
return -ERESTARTNOHAND;
|
||||
}
|
||||
|
||||
if (skb->len > count) {
|
||||
skb_queue_head(&stream->stream->recv_queue, skb);
|
||||
return -EMSGSIZE;
|
||||
}
|
||||
|
||||
if (copy_to_user(buffer, skb->data, skb->len)) {
|
||||
skb_queue_head(&stream->stream->recv_queue, skb);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
count = skb->len;
|
||||
|
||||
kfree_skb(skb);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t tapi_stream_write(struct file *file, const char __user *buffer,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct tapi_stream_file *stream = file->private_data;
|
||||
struct tapi_device *tdev = stream->tdev;
|
||||
struct sk_buff *skb;
|
||||
|
||||
if (count == 0)
|
||||
return 0;
|
||||
|
||||
skb = alloc_skb(count, GFP_USER);
|
||||
if (!skb)
|
||||
return -ENOMEM;
|
||||
|
||||
if (copy_from_user(skb_put(skb, count), buffer, count)) {
|
||||
kfree_skb(skb);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
tdev->ops->stream_send(tdev, stream->stream, skb);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static const struct file_operations tapi_stream_file_ops = {
|
||||
.owner = THIS_MODULE,
|
||||
.read = tapi_stream_read,
|
||||
.write = tapi_stream_write,
|
||||
.open = tapi_stream_open,
|
||||
.release = tapi_stream_release,
|
||||
.poll = tapi_stream_poll,
|
||||
.unlocked_ioctl = tapi_stream_ioctl,
|
||||
};
|
||||
|
||||
int tapi_register_stream_device(struct tapi_device* tdev)
|
||||
{
|
||||
dev_set_name(&tdev->stream_dev.dev, "tapi%uS", tdev->id);
|
||||
return tapi_char_device_register(tdev, &tdev->stream_dev, &tapi_stream_file_ops);
|
||||
}
|
||||
|
||||
int tapi_stream_recv(struct tapi_device *tdev, struct tapi_stream * stream,
|
||||
struct sk_buff *skb)
|
||||
{
|
||||
skb_queue_tail(&stream->recv_queue, skb);
|
||||
wake_up(&stream->recv_wait);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(tapi_stream_recv);
|
|
@ -1,107 +0,0 @@
|
|||
#include <linux/device.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/sysfs.h>
|
||||
|
||||
#include <linux/err.h>
|
||||
#include <linux/tapi/tapi.h>
|
||||
|
||||
struct tapi_sysfs_port {
|
||||
struct tapi_device *tdev;
|
||||
unsigned int id;
|
||||
struct kobject kobj;
|
||||
};
|
||||
|
||||
struct tapi_sysfs_entry {
|
||||
ssize_t (*show)(struct tapi_device *, unsigned int port, char *);
|
||||
ssize_t (*store)(struct tapi_device *, unsigned int port, const char *, size_t);
|
||||
struct attribute attr;
|
||||
};
|
||||
|
||||
static ssize_t tapi_port_store(struct kobject *kobj, struct attribute *attr,
|
||||
const char *s, size_t len)
|
||||
{
|
||||
struct tapi_sysfs_port *port = container_of(kobj, struct tapi_sysfs_port, kobj);
|
||||
struct tapi_sysfs_entry *entry = container_of(attr, struct tapi_sysfs_entry,
|
||||
attr);
|
||||
|
||||
if (!entry->store)
|
||||
return -ENOSYS;
|
||||
|
||||
return entry->store(port->tdev, port->id, s, len);
|
||||
}
|
||||
|
||||
static ssize_t tapi_port_show(struct kobject *kobj, struct attribute *attr,
|
||||
char *s)
|
||||
{
|
||||
return -ENOSYS;
|
||||
}
|
||||
|
||||
#define TAPI_PORT_ATTR(_name, _mode, _show, _store) \
|
||||
struct tapi_sysfs_entry tapi_port_ ## _name ## _attr = \
|
||||
__ATTR(_name, _mode, _show, _store)
|
||||
|
||||
static int tapi_port_store_ring(struct tapi_device *tdev, unsigned int port,
|
||||
const char *s, size_t len)
|
||||
{
|
||||
int ret;
|
||||
unsigned long val;
|
||||
|
||||
ret = strict_strtoul(s, 10, &val);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = tapi_port_set_ring(tdev, &tdev->ports[port], val);
|
||||
if (ret)
|
||||
return ret;
|
||||
return len;
|
||||
}
|
||||
|
||||
static TAPI_PORT_ATTR(ring, 0644, NULL, tapi_port_store_ring);
|
||||
|
||||
static struct attribute *tapi_port_default_attrs[] = {
|
||||
&tapi_port_ring_attr.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static void tapi_port_free(struct kobject *kobj)
|
||||
{
|
||||
struct tapi_sysfs_port *port = container_of(kobj, struct tapi_sysfs_port, kobj);
|
||||
kfree(port);
|
||||
}
|
||||
|
||||
static struct sysfs_ops tapi_port_sysfs_ops = {
|
||||
.show = tapi_port_show,
|
||||
.store = tapi_port_store,
|
||||
};
|
||||
|
||||
static struct kobj_type tapi_port_ktype = {
|
||||
.release = tapi_port_free,
|
||||
.sysfs_ops = &tapi_port_sysfs_ops,
|
||||
.default_attrs = tapi_port_default_attrs,
|
||||
};
|
||||
|
||||
struct tapi_sysfs_port *tapi_port_alloc(struct tapi_device *tdev, unsigned int id)
|
||||
{
|
||||
struct tapi_sysfs_port *port;
|
||||
int ret;
|
||||
|
||||
port = kzalloc(sizeof(*port), GFP_KERNEL);
|
||||
port->tdev = tdev;
|
||||
port->id = id;
|
||||
|
||||
ret = kobject_init_and_add(&port->kobj, &tapi_port_ktype, &tdev->dev.kobj,
|
||||
"port%d", id);
|
||||
if (ret) {
|
||||
kfree(port);
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
return port;
|
||||
}
|
||||
|
||||
void tapi_port_delete(struct tapi_sysfs_port *port)
|
||||
{
|
||||
kobject_del(&port->kobj);
|
||||
kobject_put(&port->kobj);
|
||||
}
|
|
@ -155,12 +155,12 @@ define Build/InstallDev
|
|||
$(CP) $(PKG_BUILD_DIR)/src/include/drv_dsl_cpe_cmv_danube.h $(1)/usr/include
|
||||
endef
|
||||
|
||||
define Package/ltq-dsl-firmware-a/install
|
||||
define Package/kmod-ltq-dsl-firmware-a/install
|
||||
$(INSTALL_DIR) $(1)/lib/firmware/
|
||||
$(CP) $(PKG_BUILD_DIR)/$(FW_BASE_NAME)_a_$(FW_A_FILE_VER).bin $(1)/lib/firmware/ModemHWE.bin
|
||||
endef
|
||||
|
||||
define Package/ltq-dsl-firmware-b/install
|
||||
define Package/kmod-ltq-dsl-firmware-b/install
|
||||
$(INSTALL_DIR) $(1)/lib/firmware/
|
||||
$(CP) $(PKG_BUILD_DIR)/$(FW_BASE_NAME)_b_$(FW_B_FILE_VER).bin $(1)/lib/firmware/ModemHWE.bin
|
||||
endef
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
Index: drv_dsl_cpe_api-3.24.4.4/configure.in
|
||||
===================================================================
|
||||
--- drv_dsl_cpe_api-3.24.4.4.orig/configure.in 2009-08-13 13:39:21.000000000 +0200
|
||||
+++ drv_dsl_cpe_api-3.24.4.4/configure.in 2010-10-14 02:14:55.000000000 +0200
|
||||
--- a/configure.in
|
||||
+++ b/configure.in
|
||||
@@ -310,7 +310,7 @@
|
||||
AC_ARG_ENABLE(kernelbuild,
|
||||
AC_HELP_STRING(--enable-kernel-build=x,Set the target kernel build path),
|
||||
|
@ -167,10 +165,8 @@ Index: drv_dsl_cpe_api-3.24.4.4/configure.in
|
|||
])
|
||||
|
||||
AC_CONFIG_FILES([Makefile src/Makefile])
|
||||
Index: drv_dsl_cpe_api-3.24.4.4/src/Makefile.am
|
||||
===================================================================
|
||||
--- drv_dsl_cpe_api-3.24.4.4.orig/src/Makefile.am 2009-07-03 14:06:34.000000000 +0200
|
||||
+++ drv_dsl_cpe_api-3.24.4.4/src/Makefile.am 2010-10-14 02:14:55.000000000 +0200
|
||||
--- a/src/Makefile.am
|
||||
+++ b/src/Makefile.am
|
||||
@@ -303,7 +303,7 @@
|
||||
drv_dsl_cpe_api_OBJS = "$(subst .c,.o,$(filter %.c,$(drv_dsl_cpe_api_SOURCES)))"
|
||||
|
||||
|
@ -195,10 +191,8 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/Makefile.am
|
|||
$(MAKE) ARCH=@KERNEL_ARCH@ -C @KERNEL_BUILD_PATH@ O=@KERNEL_BUILD_PATH@ M=$(PWD) modules
|
||||
|
||||
clean-generic:
|
||||
Index: drv_dsl_cpe_api-3.24.4.4/src/include/drv_dsl_cpe_os_linux.h
|
||||
===================================================================
|
||||
--- drv_dsl_cpe_api-3.24.4.4.orig/src/include/drv_dsl_cpe_os_linux.h 2010-10-14 02:14:55.000000000 +0200
|
||||
+++ drv_dsl_cpe_api-3.24.4.4/src/include/drv_dsl_cpe_os_linux.h 2010-10-14 02:14:55.000000000 +0200
|
||||
--- a/src/include/drv_dsl_cpe_os_linux.h
|
||||
+++ b/src/include/drv_dsl_cpe_os_linux.h
|
||||
@@ -16,8 +16,6 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -208,10 +202,25 @@ Index: drv_dsl_cpe_api-3.24.4.4/src/include/drv_dsl_cpe_os_linux.h
|
|||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/init.h>
|
||||
@@ -40,6 +38,7 @@
|
||||
@@ -26,8 +24,10 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/sched.h>
|
||||
|
||||
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
|
||||
- #include <generated/utsrelease.h>
|
||||
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
|
||||
+#include <linux/utsrelease.h>
|
||||
+#else
|
||||
+#include <generated/utsrelease.h>
|
||||
#endif
|
||||
|
||||
#include <linux/types.h>
|
||||
@@ -39,7 +39,8 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/poll.h>
|
||||
#include <asm/uaccess.h>
|
||||
#include <linux/smp_lock.h>
|
||||
-#include <linux/smp_lock.h>
|
||||
+//#include <linux/smp_lock.h>
|
||||
+#include <asm/ioctl.h>
|
||||
|
||||
#ifdef INCLUDE_DSL_CPE_API_IFXOS_SUPPORT
|
||||
|
|
|
@ -59,8 +59,7 @@
|
|||
/*
|
||||
* Chip Specific Head File
|
||||
*/
|
||||
#include <lantiq.h>
|
||||
#include <lantiq_regs.h>
|
||||
#include <lantiq_soc.h>
|
||||
#include "ifxmips_atm_core.h"
|
||||
|
||||
|
||||
|
@ -2403,7 +2402,11 @@ static int __devinit ifx_atm_init(void)
|
|||
|
||||
/* create devices */
|
||||
for ( port_num = 0; port_num < ATM_PORT_NUMBER; port_num++ ) {
|
||||
g_atm_priv_data.port[port_num].dev = atm_dev_register("ifxmips_atm", NULL, &g_ifx_atm_ops, -1, NULL);
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
|
||||
g_atm_priv_data.port[port_num].dev = atm_dev_register("ifxmips_atm", &g_ifx_atm_ops, -1, NULL);
|
||||
#else
|
||||
g_atm_priv_data.port[port_num].dev = atm_dev_register("ifxmips_atm", NULL, &g_ifx_atm_ops, -1, NULL);
|
||||
#endif
|
||||
if ( !g_atm_priv_data.port[port_num].dev ) {
|
||||
err("failed to register atm device %d!", port_num);
|
||||
ret = -EIO;
|
||||
|
|
|
@ -45,8 +45,7 @@
|
|||
/*
|
||||
* Chip Specific Head File
|
||||
*/
|
||||
#include <lantiq.h>
|
||||
#include <lantiq_regs.h>
|
||||
#include <lantiq_soc.h>
|
||||
#include "ifxmips_compat.h"
|
||||
#include "ifxmips_atm_core.h"
|
||||
#include "ifxmips_atm_fw_danube.h"
|
||||
|
|
|
@ -93,7 +93,7 @@
|
|||
/*
|
||||
* Mailbox IGU1 Interrupt
|
||||
*/
|
||||
#define PPE_MAILBOX_IGU1_INT LQ_PPE_MBOX_INT
|
||||
#define PPE_MAILBOX_IGU1_INT LTQ_PPE_MBOX_INT
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
#define IFX_PMU_MODULE_PPE_EMA (1 << 22)
|
||||
#define IFX_PMU_MODULE_PPE_TOP (1 << 29)
|
||||
|
||||
#define ifx_pmu_set(a,b) {if(a == IFX_PMU_ENABLE) lq_pmu_enable(b); else lq_pmu_disable(b);}
|
||||
#define ifx_pmu_set(a,b) {if(a == IFX_PMU_ENABLE) ltq_pmu_enable(b); else ltq_pmu_disable(b);}
|
||||
|
||||
#define PPE_TOP_PMU_SETUP(__x) ifx_pmu_set(IFX_PMU_MODULE_PPE_TOP, (__x))
|
||||
#define PPE_SLL01_PMU_SETUP(__x) ifx_pmu_set(IFX_PMU_MODULE_PPE_SLL01, (__x))
|
||||
|
|
|
@ -29,7 +29,11 @@
|
|||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/version.h>
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
|
||||
#include <linux/utsrelease.h>
|
||||
#else
|
||||
#include <generated/utsrelease.h>
|
||||
#endif
|
||||
#include <linux/types.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/mm.h>
|
||||
|
@ -46,22 +50,21 @@
|
|||
#include <asm/uaccess.h>
|
||||
#include <asm/hardirq.h>
|
||||
|
||||
#include <lantiq.h>
|
||||
#include <lantiq_regs.h>
|
||||
#include <lantiq_soc.h>
|
||||
#include "ifxmips_atm.h"
|
||||
#define IFX_MEI_BSP
|
||||
#include "ifxmips_mei_interface.h"
|
||||
|
||||
/*#define LQ_RCU_RST IFX_RCU_RST_REQ
|
||||
#define LQ_RCU_RST_REQ_ARC_JTAG IFX_RCU_RST_REQ_ARC_JTAG
|
||||
#define LQ_RCU_RST_REQ_DFE IFX_RCU_RST_REQ_DFE
|
||||
#define LQ_RCU_RST_REQ_AFE IFX_RCU_RST_REQ_AFE
|
||||
/*#define LTQ_RCU_RST IFX_RCU_RST_REQ
|
||||
#define LTQ_RCU_RST_REQ_ARC_JTAG IFX_RCU_RST_REQ_ARC_JTAG
|
||||
#define LTQ_RCU_RST_REQ_DFE IFX_RCU_RST_REQ_DFE
|
||||
#define LTQ_RCU_RST_REQ_AFE IFX_RCU_RST_REQ_AFE
|
||||
#define IFXMIPS_FUSE_BASE_ADDR IFX_FUSE_BASE_ADDR
|
||||
#define IFXMIPS_ICU_IM0_IER IFX_ICU_IM0_IER
|
||||
#define IFXMIPS_ICU_IM2_IER IFX_ICU_IM2_IER
|
||||
#define LQ_MEI_INT IFX_MEI_INT
|
||||
#define LQ_MEI_DYING_GASP_INT IFX_MEI_DYING_GASP_INT
|
||||
#define LQ_MEI_BASE_ADDR IFX_MEI_SPACE_ACCESS
|
||||
#define LTQ_MEI_INT IFX_MEI_INT
|
||||
#define LTQ_MEI_DYING_GASP_INT IFX_MEI_DYING_GASP_INT
|
||||
#define LTQ_MEI_BASE_ADDR IFX_MEI_SPACE_ACCESS
|
||||
#define IFXMIPS_PMU_PWDCR IFX_PMU_PWDCR
|
||||
#define IFXMIPS_MPS_CHIPID IFX_MPS_CHIPID
|
||||
|
||||
|
@ -73,40 +76,44 @@
|
|||
#define ifxmips_port_free_pin ifx_gpio_pin_free
|
||||
#define ifxmips_mask_and_ack_irq bsp_mask_and_ack_irq
|
||||
#define IFXMIPS_MPS_CHIPID_VERSION_GET IFX_MCD_CHIPID_VERSION_GET
|
||||
#define lq_r32(reg) __raw_readl(reg)
|
||||
#define lq_w32(val, reg) __raw_writel(val, reg)
|
||||
#define lq_w32_mask(clear, set, reg) lq_w32((lq_r32(reg) & ~clear) | set, reg)
|
||||
#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 LQ_RCU_RST_REQ_DFE (1 << 7)
|
||||
#define LQ_RCU_RST_REQ_AFE (1 << 11)
|
||||
#define LQ_PMU_PWDCR ((u32 *)(LQ_PMU_BASE_ADDR + 0x001C))
|
||||
#define LQ_PMU_PWDSR ((u32 *)(LQ_PMU_BASE_ADDR + 0x0020))
|
||||
#define LQ_RCU_RST ((u32 *)(LQ_RCU_BASE_ADDR + 0x0010))
|
||||
#define LQ_RCU_RST_ALL 0x40000000
|
||||
#define LQ_ICU_BASE_ADDR (KSEG1 | 0x1F880200)
|
||||
#define LTQ_RCU_RST_REQ_DFE (1 << 7)
|
||||
#define LTQ_RCU_RST_REQ_AFE (1 << 11)
|
||||
|
||||
#define LQ_ICU_IM0_ISR ((u32 *)(LQ_ICU_BASE_ADDR + 0x0000))
|
||||
#define LQ_ICU_IM0_IER ((u32 *)(LQ_ICU_BASE_ADDR + 0x0008))
|
||||
#define LQ_ICU_IM0_IOSR ((u32 *)(LQ_ICU_BASE_ADDR + 0x0010))
|
||||
#define LQ_ICU_IM0_IRSR ((u32 *)(LQ_ICU_BASE_ADDR + 0x0018))
|
||||
#define LQ_ICU_IM0_IMR ((u32 *)(LQ_ICU_BASE_ADDR + 0x0020))
|
||||
#define LTQ_PMU_BASE (KSEG1 + LTQ_PMU_BASE_ADDR)
|
||||
#define LTQ_RCU_BASE (KSEG1 + LTQ_RCU_BASE_ADDR)
|
||||
#define LTQ_ICU_BASE (KSEG1 + LTQ_ICU_BASE_ADDR)
|
||||
|
||||
#define LTQ_PMU_PWDCR ((u32 *)(LTQ_PMU_BASE + 0x001C))
|
||||
#define LTQ_PMU_PWDSR ((u32 *)(LTQ_PMU_BASE + 0x0020))
|
||||
#define LTQ_RCU_RST ((u32 *)(LTQ_RCU_BASE + 0x0010))
|
||||
#define LTQ_RCU_RST_ALL 0x40000000
|
||||
|
||||
#define LTQ_ICU_IM0_ISR ((u32 *)(LTQ_ICU_BASE + 0x0000))
|
||||
#define LTQ_ICU_IM0_IER ((u32 *)(LTQ_ICU_BASE + 0x0008))
|
||||
#define LTQ_ICU_IM0_IOSR ((u32 *)(LTQ_ICU_BASE + 0x0010))
|
||||
#define LTQ_ICU_IM0_IRSR ((u32 *)(LTQ_ICU_BASE + 0x0018))
|
||||
#define LTQ_ICU_IM0_IMR ((u32 *)(LTQ_ICU_BASE + 0x0020))
|
||||
|
||||
|
||||
#define LQ_ICU_IM1_ISR ((u32 *)(LQ_ICU_BASE_ADDR + 0x0028))
|
||||
#define LQ_ICU_IM2_ISR ((u32 *)(LQ_ICU_BASE_ADDR + 0x0050))
|
||||
#define LQ_ICU_IM3_ISR ((u32 *)(LQ_ICU_BASE_ADDR + 0x0078))
|
||||
#define LQ_ICU_IM4_ISR ((u32 *)(LQ_ICU_BASE_ADDR + 0x00A0))
|
||||
#define LTQ_ICU_IM1_ISR ((u32 *)(LTQ_ICU_BASE + 0x0028))
|
||||
#define LTQ_ICU_IM2_ISR ((u32 *)(LTQ_ICU_BASE + 0x0050))
|
||||
#define LTQ_ICU_IM3_ISR ((u32 *)(LTQ_ICU_BASE + 0x0078))
|
||||
#define LTQ_ICU_IM4_ISR ((u32 *)(LTQ_ICU_BASE + 0x00A0))
|
||||
|
||||
#define LQ_ICU_OFFSET (LQ_ICU_IM1_ISR - LQ_ICU_IM0_ISR)
|
||||
#define LQ_ICU_IM2_IER (LQ_ICU_IM0_IER + LQ_ICU_OFFSET)
|
||||
#define LTQ_ICU_OFFSET (LTQ_ICU_IM1_ISR - LTQ_ICU_IM0_ISR)
|
||||
#define LTQ_ICU_IM2_IER (LTQ_ICU_IM0_IER + LTQ_ICU_OFFSET)
|
||||
|
||||
#define IFX_MEI_EMSG(fmt, args...) pr_err("[%s %d]: " fmt,__FUNCTION__, __LINE__, ## args)
|
||||
#define IFX_MEI_DMSG(fmt, args...) pr_debug("[%s %d]: " fmt,__FUNCTION__, __LINE__, ## args)
|
||||
|
||||
#define LQ_FUSE_BASE (KSEG1 + 0x1F107354)
|
||||
#define LTQ_FUSE_BASE (KSEG1 + 0x1F107354)
|
||||
|
||||
#ifdef CONFIG_LQ_MEI_FW_LOOPBACK
|
||||
#ifdef CONFIG_LTQ_MEI_FW_LOOPBACK
|
||||
//#define DFE_MEM_TEST
|
||||
//#define DFE_PING_TEST
|
||||
#define DFE_ATM_LOOPBACK
|
||||
|
@ -193,9 +200,18 @@ static void *g_xdata_addr = NULL;
|
|||
|
||||
static u32 *mei_arc_swap_buff = NULL; // holding swap pages
|
||||
|
||||
extern void lq_mask_and_ack_irq(unsigned int irq_nr);
|
||||
#define MEI_MASK_AND_ACK_IRQ lq_mask_and_ack_irq
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
|
||||
extern void ltq_mask_and_ack_irq(unsigned int irq_nr);
|
||||
#define MEI_MASK_AND_ACK_IRQ ltq_mask_and_ack_irq
|
||||
#else
|
||||
extern void ltq_mask_and_ack_irq(struct irq_data *d);
|
||||
static void inline MEI_MASK_AND_ACK_IRQ(int x)
|
||||
{
|
||||
struct irq_data d;
|
||||
d.irq = x;
|
||||
ltq_mask_and_ack_irq(&d);
|
||||
}
|
||||
#endif
|
||||
#define MEI_MAJOR 105
|
||||
static int dev_major = MEI_MAJOR;
|
||||
|
||||
|
@ -704,9 +720,9 @@ IFX_MEI_FuseProg (DSL_DEV_Device_t * pDev)
|
|||
u32 reg_data, fuse_value;
|
||||
int i = 0;
|
||||
|
||||
IFX_MEI_LongWordRead ((u32) LQ_RCU_RST, ®_data);
|
||||
IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, ®_data);
|
||||
while ((reg_data & 0x10000000) == 0) {
|
||||
IFX_MEI_LongWordRead ((u32) LQ_RCU_RST, ®_data);
|
||||
IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, ®_data);
|
||||
i++;
|
||||
/* 0x4000 translate to about 16 ms@111M, so should be enough */
|
||||
if (i == 0x4000)
|
||||
|
@ -714,12 +730,12 @@ IFX_MEI_FuseProg (DSL_DEV_Device_t * pDev)
|
|||
}
|
||||
// STEP a: Prepare memory for external accesses
|
||||
// Write fuse_en bit24
|
||||
IFX_MEI_LongWordRead ((u32) LQ_RCU_RST, ®_data);
|
||||
IFX_MEI_LongWordWrite ((u32) LQ_RCU_RST, reg_data | (1 << 24));
|
||||
IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, ®_data);
|
||||
IFX_MEI_LongWordWrite ((u32) LTQ_RCU_RST, reg_data | (1 << 24));
|
||||
|
||||
IFX_MEI_FuseInit (pDev);
|
||||
for (i = 0; i < 4; i++) {
|
||||
IFX_MEI_LongWordRead ((u32) (LQ_FUSE_BASE) + i * 4, &fuse_value);
|
||||
IFX_MEI_LongWordRead ((u32) (LTQ_FUSE_BASE) + i * 4, &fuse_value);
|
||||
switch (fuse_value & 0xF0000) {
|
||||
case 0x80000:
|
||||
reg_data = ((fuse_value & RX_DILV_ADDR_BIT_MASK) |
|
||||
|
@ -765,9 +781,9 @@ IFX_MEI_FuseProg (DSL_DEV_Device_t * pDev)
|
|||
break;
|
||||
}
|
||||
}
|
||||
IFX_MEI_LongWordRead ((u32) LQ_RCU_RST, ®_data);
|
||||
IFX_MEI_LongWordWrite ((u32) LQ_RCU_RST, reg_data & ~(1 << 24));
|
||||
IFX_MEI_LongWordRead ((u32) LQ_RCU_RST, ®_data);
|
||||
IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, ®_data);
|
||||
IFX_MEI_LongWordWrite ((u32) LTQ_RCU_RST, reg_data & ~(1 << 24));
|
||||
IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, ®_data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -868,9 +884,9 @@ IFX_MEI_ResetARC (DSL_DEV_Device_t * pDev)
|
|||
|
||||
IFX_MEI_HaltArc (pDev);
|
||||
|
||||
IFX_MEI_LongWordRead ((u32) LQ_RCU_RST, &arc_debug_data);
|
||||
IFX_MEI_LongWordWrite ((u32) LQ_RCU_RST,
|
||||
arc_debug_data | LQ_RCU_RST_REQ_DFE | LQ_RCU_RST_REQ_AFE);
|
||||
IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, &arc_debug_data);
|
||||
IFX_MEI_LongWordWrite ((u32) LTQ_RCU_RST,
|
||||
arc_debug_data | LTQ_RCU_RST_REQ_DFE | LTQ_RCU_RST_REQ_AFE);
|
||||
|
||||
// reset ARC
|
||||
IFX_MEI_LongWordWriteOffset (pDev, (u32) ME_RST_CTRL, MEI_SOFT_RESET);
|
||||
|
@ -1034,8 +1050,8 @@ IFX_MEI_ArcJtagEnable (DSL_DEV_Device_t *dev, int enable)
|
|||
ifxmips_port_clear_altsel1(0, 11);
|
||||
ifxmips_port_set_open_drain(0, 11);
|
||||
//enable ARC JTAG
|
||||
IFX_MEI_LongWordRead ((u32) LQ_RCU_RST, ®_data);
|
||||
IFX_MEI_LongWordWrite ((u32) LQ_RCU_RST, reg_data | LQ_RCU_RST_REQ_ARC_JTAG);
|
||||
IFX_MEI_LongWordRead ((u32) LTQ_RCU_RST, ®_data);
|
||||
IFX_MEI_LongWordWrite ((u32) LTQ_RCU_RST, reg_data | LTQ_RCU_RST_REQ_ARC_JTAG);
|
||||
break;
|
||||
case 0:
|
||||
default:
|
||||
|
@ -1045,8 +1061,6 @@ jtag_end:
|
|||
if (meierr)
|
||||
return DSL_DEV_MEI_ERR_FAILURE;
|
||||
*/
|
||||
printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
|
||||
printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
|
||||
|
||||
return DSL_DEV_MEI_ERR_SUCCESS;
|
||||
};
|
||||
|
@ -1333,17 +1347,17 @@ IFX_MEI_RunAdslModem (DSL_DEV_Device_t *pDev)
|
|||
|
||||
IFX_MEI_DownloadBootCode (pDev);
|
||||
|
||||
im0_register = (*LQ_ICU_IM0_IER) & (1 << 20);
|
||||
im2_register = (*LQ_ICU_IM2_IER) & (1 << 20);
|
||||
im0_register = (*LTQ_ICU_IM0_IER) & (1 << 20);
|
||||
im2_register = (*LTQ_ICU_IM2_IER) & (1 << 20);
|
||||
/* Turn off irq */
|
||||
#ifdef CONFIG_LANTIQ_AMAZON_SE
|
||||
#ifdef CONFIG_SOC_AMAZON_SE
|
||||
disable_irq (IFXMIPS_USB_OC_INT0);
|
||||
disable_irq (IFXMIPS_USB_OC_INT2);
|
||||
#elif defined(CONFIG_LANTIQ_AR9)
|
||||
disable_irq (IFXMIPS_USB_OC_INT0);
|
||||
disable_irq (IFXMIPS_USB_OC_INT2);
|
||||
#elif defined(CONFIG_SOC_LANTIQ_XWAY)
|
||||
disable_irq (LQ_USB_OC_INT);
|
||||
#elif defined(CONFIG_SOC_XWAY)
|
||||
disable_irq (LTQ_USB_OC_INT);
|
||||
#else
|
||||
#error unkonwn arch
|
||||
#endif
|
||||
|
@ -1353,14 +1367,14 @@ IFX_MEI_RunAdslModem (DSL_DEV_Device_t *pDev)
|
|||
|
||||
MEI_WAIT_EVENT_TIMEOUT (DSL_DEV_PRIVATE(pDev)->wait_queue_modemready, 1000);
|
||||
|
||||
#ifdef CONFIG_LANTIQ_AMAZON_SE
|
||||
#ifdef CONFIG_SOC_AMAZON_SE
|
||||
MEI_MASK_AND_ACK_IRQ (IFXMIPS_USB_OC_INT0);
|
||||
MEI_MASK_AND_ACK_IRQ (IFXMIPS_USB_OC_INT2);
|
||||
#elif defined(CONFIG_LANTIQ_AMAZON_S)
|
||||
MEI_MASK_AND_ACK_IRQ (IFXMIPS_USB_OC_INT0);
|
||||
MEI_MASK_AND_ACK_IRQ (IFXMIPS_USB_OC_INT2);
|
||||
#elif defined(CONFIG_SOC_LANTIQ_XWAY)
|
||||
MEI_MASK_AND_ACK_IRQ (LQ_USB_OC_INT);
|
||||
#elif defined(CONFIG_SOC_XWAY)
|
||||
MEI_MASK_AND_ACK_IRQ (LTQ_USB_OC_INT);
|
||||
#else
|
||||
#error unkonwn arch
|
||||
#endif
|
||||
|
@ -1368,8 +1382,8 @@ IFX_MEI_RunAdslModem (DSL_DEV_Device_t *pDev)
|
|||
|
||||
/* Re-enable irq */
|
||||
enable_irq(pDev->nIrq[IFX_DYING_GASP]);
|
||||
*LQ_ICU_IM0_IER |= im0_register;
|
||||
*LQ_ICU_IM2_IER |= im2_register;
|
||||
*LTQ_ICU_IM0_IER |= im0_register;
|
||||
*LTQ_ICU_IM2_IER |= im2_register;
|
||||
|
||||
if (DSL_DEV_PRIVATE(pDev)->modem_ready != 1) {
|
||||
IFX_MEI_EMSG ("Modem failed to be ready!\n");
|
||||
|
@ -1780,7 +1794,7 @@ static irqreturn_t IFX_MEI_IrqHandle (int int1, void *void0)
|
|||
{
|
||||
u32 scratch;
|
||||
DSL_DEV_Device_t *pDev = (DSL_DEV_Device_t *) void0;
|
||||
#if defined(CONFIG_LQ_MEI_FW_LOOPBACK) && defined(DFE_PING_TEST)
|
||||
#if defined(CONFIG_LTQ_MEI_FW_LOOPBACK) && defined(DFE_PING_TEST)
|
||||
dfe_loopback_irq_handler (pDev);
|
||||
return IRQ_HANDLED;
|
||||
#endif //CONFIG_AMAZON_S_MEI_FW_LOOPBACK
|
||||
|
@ -1889,7 +1903,7 @@ DSL_BSP_GetEventCB (int (**ifx_adsl_callback)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_LQ_MEI_FW_LOOPBACK
|
||||
#ifdef CONFIG_LTQ_MEI_FW_LOOPBACK
|
||||
#define mte_reg_base (0x4800*4+0x20000)
|
||||
|
||||
/* Iridia Registers Address Constants */
|
||||
|
@ -1949,20 +1963,20 @@ MEIWriteARCValue (u32 address, u32 value)
|
|||
u32 i, check = 0;
|
||||
|
||||
/* Write address register */
|
||||
IFX_MEI_WRITE_REGISTER_L (address, ME_DBG_WR_AD + LQ_MEI_BASE_ADDR);
|
||||
IFX_MEI_WRITE_REGISTER_L (address, ME_DBG_WR_AD + LTQ_MEI_BASE_ADDR);
|
||||
|
||||
/* Write data register */
|
||||
IFX_MEI_WRITE_REGISTER_L (value, ME_DBG_DATA + LQ_MEI_BASE_ADDR);
|
||||
IFX_MEI_WRITE_REGISTER_L (value, ME_DBG_DATA + LTQ_MEI_BASE_ADDR);
|
||||
|
||||
/* wait until complete - timeout at 40 */
|
||||
for (i = 0; i < 40; i++) {
|
||||
check = IFX_MEI_READ_REGISTER_L (ME_ARC2ME_STAT + LQ_MEI_BASE_ADDR);
|
||||
check = IFX_MEI_READ_REGISTER_L (ME_ARC2ME_STAT + LTQ_MEI_BASE_ADDR);
|
||||
|
||||
if ((check & ARC_TO_MEI_DBG_DONE))
|
||||
break;
|
||||
}
|
||||
/* clear the flag */
|
||||
IFX_MEI_WRITE_REGISTER_L (ARC_TO_MEI_DBG_DONE, ME_ARC2ME_STAT + LQ_MEI_BASE_ADDR);
|
||||
IFX_MEI_WRITE_REGISTER_L (ARC_TO_MEI_DBG_DONE, ME_ARC2ME_STAT + LTQ_MEI_BASE_ADDR);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2145,7 +2159,7 @@ DFE_Loopback_Test (void)
|
|||
IFX_MEI_ControlModeSet (pDev, MEI_MASTER_MODE);
|
||||
temp = 0;
|
||||
_IFX_MEI_DBGLongWordWrite (pDev, MEI_DEBUG_DEC_AUX_MASK,
|
||||
(u32) ME_XDATA_BASE_SH + LQ_MEI_BASE_ADDR, temp);
|
||||
(u32) ME_XDATA_BASE_SH + LTQ_MEI_BASE_ADDR, temp);
|
||||
IFX_MEI_ControlModeSet (pDev, JTAG_MASTER_MODE);
|
||||
|
||||
i = IFX_MEI_DFEMemoryAlloc (pDev, SDRAM_SEGMENT_SIZE * 16);
|
||||
|
@ -2155,9 +2169,9 @@ DFE_Loopback_Test (void)
|
|||
for (idx = 0; idx < i; idx++) {
|
||||
DSL_DEV_PRIVATE(pDev)->adsl_mem_info[idx].type = FREE_RELOAD;
|
||||
IFX_MEI_WRITE_REGISTER_L ((((uint32_t) DSL_DEV_PRIVATE(pDev)->adsl_mem_info[idx].address) & 0x0fffffff),
|
||||
LQ_MEI_BASE_ADDR + ME_XMEM_BAR_BASE + idx * 4);
|
||||
LTQ_MEI_BASE_ADDR + ME_XMEM_BAR_BASE + idx * 4);
|
||||
IFX_MEI_DMSG("bar%d(%X)=%X\n", idx,
|
||||
LQ_MEI_BASE_ADDR + ME_XMEM_BAR_BASE +
|
||||
LTQ_MEI_BASE_ADDR + ME_XMEM_BAR_BASE +
|
||||
idx * 4, (((uint32_t)
|
||||
((ifx_mei_device_private_t *)
|
||||
pDev->pPriv)->adsl_mem_info[idx].
|
||||
|
@ -2271,18 +2285,18 @@ IFX_MEI_InitDevice (int num)
|
|||
sizeof (smmu_mem_info_t) * MAX_BAR_REGISTERS);
|
||||
|
||||
if (num == 0) {
|
||||
pDev->nIrq[IFX_DFEIR] = LQ_MEI_INT;
|
||||
pDev->nIrq[IFX_DYING_GASP] = LQ_MEI_DYING_GASP_INT;
|
||||
pDev->base_address = LQ_MEI_BASE_ADDR;
|
||||
pDev->nIrq[IFX_DFEIR] = LTQ_MEI_INT;
|
||||
pDev->nIrq[IFX_DYING_GASP] = LTQ_MEI_DYING_GASP_INT;
|
||||
pDev->base_address = KSEG1 + LTQ_MEI_BASE_ADDR;
|
||||
|
||||
/* Power up MEI */
|
||||
#ifdef CONFIG_LANTIQ_AMAZON_SE
|
||||
*LQ_PMU_PWDCR &= ~(1 << 9); // enable dsl
|
||||
*LQ_PMU_PWDCR &= ~(1 << 15); // enable AHB base
|
||||
*LTQ_PMU_PWDCR &= ~(1 << 9); // enable dsl
|
||||
*LTQ_PMU_PWDCR &= ~(1 << 15); // enable AHB base
|
||||
#else
|
||||
temp = lq_r32(LQ_PMU_PWDCR);
|
||||
temp = ltq_r32(LTQ_PMU_PWDCR);
|
||||
temp &= 0xffff7dbe;
|
||||
lq_w32(temp, LQ_PMU_PWDCR);
|
||||
ltq_w32(temp, LTQ_PMU_PWDCR);
|
||||
#endif
|
||||
}
|
||||
pDev->nInUse = 0;
|
||||
|
@ -2443,7 +2457,7 @@ IFX_MEI_Ioctls (DSL_DEV_Device_t * pDev, int from_kernel, unsigned int command,
|
|||
{
|
||||
int i = 0;
|
||||
int meierr = DSL_DEV_MEI_ERR_SUCCESS;
|
||||
u32 base_address = LQ_MEI_BASE_ADDR;
|
||||
u32 base_address = LTQ_MEI_BASE_ADDR;
|
||||
DSL_DEV_WinHost_Message_t winhost_msg, m;
|
||||
DSL_DEV_MeiDebug_t debugrdwr;
|
||||
DSL_DEV_MeiReg_t regrdwr;
|
||||
|
@ -2569,10 +2583,10 @@ IFX_MEI_Ioctls (DSL_DEV_Device_t * pDev, int from_kernel, unsigned int command,
|
|||
IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon, (char *) (&bsp_mei_version), sizeof (DSL_DEV_Version_t));
|
||||
break;
|
||||
|
||||
#define LQ_MPS_CHIPID_VERSION_GET(value) (((value) >> 28) & ((1 << 4) - 1))
|
||||
#define LTQ_MPS_CHIPID_VERSION_GET(value) (((value) >> 28) & ((1 << 4) - 1))
|
||||
case DSL_FIO_BSP_GET_CHIP_INFO:
|
||||
bsp_chip_info.major = 1;
|
||||
bsp_chip_info.minor = LQ_MPS_CHIPID_VERSION_GET(*LQ_MPS_CHIPID);
|
||||
bsp_chip_info.minor = LTQ_MPS_CHIPID_VERSION_GET(*LTQ_MPS_CHIPID);
|
||||
IFX_MEI_IoctlCopyTo (from_kernel, (char *) lon, (char *) (&bsp_chip_info), sizeof (DSL_DEV_HwVersion_t));
|
||||
meierr = DSL_DEV_MEI_ERR_SUCCESS;
|
||||
break;
|
||||
|
@ -2608,7 +2622,7 @@ IFX_MEI_Ioctls (DSL_DEV_Device_t * pDev, int from_kernel, unsigned int command,
|
|||
void AMAZON_SE_MEI_ARC_MUX_Test(void)
|
||||
{
|
||||
u32 *p, i;
|
||||
*LQ_RCU_RST |= LQ_RCU_RST_REQ_MUX_ARC;
|
||||
*LTQ_RCU_RST |= LTQ_RCU_RST_REQ_MUX_ARC;
|
||||
|
||||
p = (u32*)(DFE_LDST_BASE_ADDR + IRAM0_BASE);
|
||||
IFX_MEI_EMSG("Writing to IRAM0(%p)...\n", p);
|
||||
|
@ -2657,7 +2671,7 @@ void AMAZON_SE_MEI_ARC_MUX_Test(void)
|
|||
if (*p != 0xdeadbeef)
|
||||
IFX_MEI_EMSG("%p: %#x\n", p, *p);
|
||||
}
|
||||
*LQ_RCU_RST &= ~LQ_RCU_RST_REQ_MUX_ARC;
|
||||
*LTQ_RCU_RST &= ~LTQ_RCU_RST_REQ_MUX_ARC;
|
||||
}
|
||||
#endif
|
||||
int
|
||||
|
@ -2959,7 +2973,7 @@ IFX_MEI_ModuleInit (void)
|
|||
for (i = 0; i <= DSL_BSP_CB_LAST ; i++)
|
||||
dsl_bsp_event_callback[i].function = NULL;
|
||||
|
||||
#ifdef CONFIG_LQ_MEI_FW_LOOPBACK
|
||||
#ifdef CONFIG_LTQ_MEI_FW_LOOPBACK
|
||||
IFX_MEI_DMSG("Start loopback test...\n");
|
||||
DFE_Loopback_Test ();
|
||||
#endif
|
||||
|
|
|
@ -9,3 +9,15 @@
|
|||
# error "missing endian definiton"
|
||||
#endif
|
||||
|
||||
--- a/src/linux/ifxos_linux_thread_drv.c
|
||||
+++ b/src/linux/ifxos_linux_thread_drv.c
|
||||
@@ -34,7 +34,9 @@
|
||||
#include <linux/sched.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/completion.h>
|
||||
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
|
||||
#include <linux/smp_lock.h>
|
||||
+#endif
|
||||
#include <linux/signal.h>
|
||||
|
||||
|
||||
|
|
|
@ -1,6 +1,26 @@
|
|||
--- a/src/drv_tapi_linux.c
|
||||
+++ b/src/drv_tapi_linux.c
|
||||
@@ -146,8 +146,13 @@ static ssize_t ifx_tapi_write(struct fil
|
||||
@@ -47,7 +47,9 @@
|
||||
#include <linux/errno.h>
|
||||
#include <asm/uaccess.h> /* copy_from_user(), ... */
|
||||
#include <asm/byteorder.h>
|
||||
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
|
||||
#include <linux/smp_lock.h> /* lock_kernel() */
|
||||
+#endif
|
||||
#include <asm/io.h>
|
||||
|
||||
#ifdef LINUX_2_6
|
||||
@@ -65,7 +67,9 @@
|
||||
#else
|
||||
#include <linux/tqueue.h>
|
||||
#include <linux/sched.h>
|
||||
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
|
||||
#include <linux/smp_lock.h> /* lock_kernel() */
|
||||
+#endif
|
||||
#endif /* LINUX_2_6 */
|
||||
|
||||
#include "drv_tapi.h"
|
||||
@@ -133,8 +137,13 @@
|
||||
size_t count, loff_t * ppos);
|
||||
static ssize_t ifx_tapi_read(struct file * filp, char *buf,
|
||||
size_t length, loff_t * ppos);
|
||||
|
@ -14,7 +34,7 @@
|
|||
static unsigned int ifx_tapi_poll (struct file *filp, poll_table *table);
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
@@ -231,7 +236,11 @@ IFX_return_t TAPI_OS_RegisterLLDrv (IFX_
|
||||
@@ -218,7 +227,11 @@
|
||||
IFX_char_t *pRegDrvName = IFX_NULL;
|
||||
IFX_int32_t ret = 0;
|
||||
|
||||
|
@ -26,7 +46,7 @@
|
|||
{
|
||||
#ifdef MODULE
|
||||
tapi_fops.owner = THIS_MODULE;
|
||||
@@ -239,7 +248,11 @@ IFX_return_t TAPI_OS_RegisterLLDrv (IFX_
|
||||
@@ -226,7 +239,11 @@
|
||||
tapi_fops.read = ifx_tapi_read;
|
||||
tapi_fops.write = ifx_tapi_write;
|
||||
tapi_fops.poll = ifx_tapi_poll;
|
||||
|
@ -38,7 +58,7 @@
|
|||
tapi_fops.open = ifx_tapi_open;
|
||||
tapi_fops.release = ifx_tapi_release;
|
||||
}
|
||||
@@ -894,8 +907,13 @@ static IFX_uint32_t ifx_tapi_poll (struc
|
||||
@@ -881,8 +898,13 @@
|
||||
- 0 and positive values - success
|
||||
- negative value - ioctl failed
|
||||
*/
|
||||
|
@ -52,6 +72,29 @@
|
|||
{
|
||||
TAPI_FD_PRIV_DATA_t *pTapiPriv;
|
||||
IFX_TAPI_ioctlCtx_t ctx;
|
||||
@@ -3721,7 +3743,9 @@
|
||||
kernel lock (lock_kernel()). The lock must be
|
||||
grabbed before changing the terminate
|
||||
flag and released after the down() call. */
|
||||
- lock_kernel();
|
||||
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
|
||||
+ lock_kernel();
|
||||
+#endif
|
||||
mb();
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
|
||||
kill_proc(pThrCntrl->tid, SIGKILL, 1);
|
||||
@@ -3729,8 +3753,10 @@
|
||||
kill_pid(find_vpid(pThrCntrl->tid), SIGKILL, 1);
|
||||
#endif
|
||||
/* release the big kernel lock */
|
||||
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33)
|
||||
unlock_kernel();
|
||||
- wait_for_completion (&pThrCntrl->thrCompletion);
|
||||
+#endif
|
||||
+ wait_for_completion (&pThrCntrl->thrCompletion);
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23)
|
||||
/* Now we are sure the thread is in zombie state.
|
||||
--- a/src/lib/lib_fifo/lib_fifo.c
|
||||
+++ b/src/lib/lib_fifo/lib_fifo.c
|
||||
@@ -41,7 +41,7 @@
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
|
||||
#if defined SYSTEM_DANUBE
|
||||
-#include <asm/ifx/ifx_gpio.h>
|
||||
+#include <xway/xway.h>
|
||||
+#include <lantiq_soc.h>
|
||||
+
|
||||
#else
|
||||
#error no system selected
|
||||
|
@ -158,7 +158,7 @@
|
|||
+# define ifx_gptu_timer_free lq_free_timer
|
||||
+
|
||||
+
|
||||
+# define bsp_mask_and_ack_irq lq_mask_and_ack_irq
|
||||
+# define bsp_mask_and_ack_irq ltq_mask_and_ack_irq
|
||||
+#else
|
||||
+# include <asm/ifx/ifx_regs.h>
|
||||
+# include <asm/ifx/ifx_gptu.h>
|
||||
|
@ -443,14 +443,14 @@
|
|||
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28))
|
||||
+IFX_uint32_t ifx_get_cp1_size(IFX_void_t)
|
||||
+{
|
||||
+ return 2;
|
||||
+ return 1;
|
||||
+}
|
||||
+
|
||||
+unsigned int *lq_get_cp1_base(void);
|
||||
+unsigned int *ltq_get_cp1_base(void);
|
||||
+
|
||||
+IFX_uint32_t *ifx_get_cp1_base(IFX_void_t)
|
||||
+{
|
||||
+ return lq_get_cp1_base();
|
||||
+ return ltq_get_cp1_base();
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
|
@ -501,7 +501,7 @@
|
|||
+#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,28))
|
||||
+# include <lantiq.h>
|
||||
+# include <irq.h>
|
||||
+# include <xway/xway.h>
|
||||
+# include <lantiq_soc.h>
|
||||
+# include <gpio.h>
|
||||
+#define IFXMIPS_MPS_SRAM ((u32 *)(KSEG1 + 0x1F200000))
|
||||
+#define IFXMIPS_MPS_BASE_ADDR (KSEG1 + 0x1F107000)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
--- a/src/drv_vmmc_init.c
|
||||
+++ b/src/drv_vmmc_init.c
|
||||
@@ -784,7 +784,7 @@ IFX_int32_t VMMC_TAPI_LL_FW_Start(IFX_TA
|
||||
@@ -784,7 +784,7 @@
|
||||
dwld.fwDwld.length = IoInit.pram_size;
|
||||
|
||||
/* download firmware */
|
||||
|
@ -9,7 +9,7 @@
|
|||
(IFX_uint32_t) &dwld.fwDwld);
|
||||
}
|
||||
|
||||
@@ -1594,7 +1594,7 @@ IFX_void_t VMMC_DeviceDriverStop(IFX_voi
|
||||
@@ -1594,7 +1594,7 @@
|
||||
#ifdef VMMC_DRIVER_UNLOAD_HOOK
|
||||
if (VDevices[0].nDevState & DS_GPIO_RESERVED)
|
||||
{
|
||||
|
@ -20,7 +20,7 @@
|
|||
{
|
||||
--- a/src/mps/drv_mps_vmmc_linux.c
|
||||
+++ b/src/mps/drv_mps_vmmc_linux.c
|
||||
@@ -110,7 +110,7 @@ IFX_int32_t ifx_mps_get_status_proc (IFX
|
||||
@@ -110,7 +110,7 @@
|
||||
#ifndef __KERNEL__
|
||||
IFX_int32_t ifx_mps_open (struct inode *inode, struct file *file_p);
|
||||
IFX_int32_t ifx_mps_close (struct inode *inode, struct file *file_p);
|
||||
|
@ -29,7 +29,7 @@
|
|||
IFX_uint32_t nCmd, IFX_ulong_t arg);
|
||||
IFX_int32_t ifx_mps_read_mailbox (mps_devices type, mps_message * rw);
|
||||
IFX_int32_t ifx_mps_write_mailbox (mps_devices type, mps_message * rw);
|
||||
@@ -171,7 +171,7 @@ IFX_char_t voice_channel_int_name[NUM_VO
|
||||
@@ -171,7 +171,7 @@
|
||||
static struct file_operations ifx_mps_fops = {
|
||||
owner:THIS_MODULE,
|
||||
poll:ifx_mps_poll,
|
||||
|
@ -38,7 +38,7 @@
|
|||
open:ifx_mps_open,
|
||||
release:ifx_mps_close
|
||||
};
|
||||
@@ -614,7 +614,7 @@ static IFX_uint32_t ifx_mps_poll (struct
|
||||
@@ -614,7 +614,7 @@
|
||||
* \return -ENOIOCTLCMD Invalid command
|
||||
* \ingroup API
|
||||
*/
|
||||
|
@ -47,7 +47,7 @@
|
|||
IFX_uint32_t nCmd, IFX_ulong_t arg)
|
||||
{
|
||||
IFX_int32_t retvalue = -EINVAL;
|
||||
@@ -629,17 +629,18 @@ IFX_int32_t ifx_mps_ioctl (struct inode
|
||||
@@ -629,17 +629,18 @@
|
||||
'mps_devices' enum type, which in fact is [0..8]; So, if inode value is
|
||||
[0..NUM_VOICE_CHANNEL+1], then we make sure that we are calling from
|
||||
kernel space. */
|
||||
|
@ -71,7 +71,7 @@
|
|||
{
|
||||
--- a/src/drv_vmmc_ioctl.c
|
||||
+++ b/src/drv_vmmc_ioctl.c
|
||||
@@ -427,18 +427,18 @@ IFX_int32_t VMMC_Dev_Spec_Ioctl (IFX_TAP
|
||||
@@ -427,18 +427,18 @@
|
||||
/* MPS driver will do the USR2KERN so just pass on the pointer. */
|
||||
dwnld_struct.data = (IFX_void_t *)IoInit.pPRAMfw;
|
||||
|
||||
|
@ -95,7 +95,7 @@
|
|||
case FIO_LASTERR:
|
||||
--- a/src/mps/drv_mps_vmmc.h
|
||||
+++ b/src/mps/drv_mps_vmmc.h
|
||||
@@ -279,7 +279,7 @@ typedef struct
|
||||
@@ -279,7 +279,7 @@
|
||||
#include <linux/fs.h>
|
||||
IFX_int32_t ifx_mps_open (struct inode *inode, struct file *file_p);
|
||||
IFX_int32_t ifx_mps_close (struct inode *inode, struct file *filp);
|
||||
|
@ -104,3 +104,89 @@
|
|||
IFX_uint32_t nCmd, unsigned long arg);
|
||||
IFX_int32_t ifx_mps_register_data_callback (mps_devices type, IFX_uint32_t dir,
|
||||
IFX_void_t (*callback) (mps_devices
|
||||
--- a/src/drv_vmmc_linux.c
|
||||
+++ b/src/drv_vmmc_linux.c
|
||||
@@ -32,7 +32,11 @@
|
||||
#ifdef LINUX_2_6
|
||||
#include <linux/version.h>
|
||||
#ifndef UTS_RELEASE
|
||||
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
|
||||
+#include <linux/utsrelease.h>
|
||||
+#else
|
||||
#include <generated/utsrelease.h>
|
||||
+#endif
|
||||
#endif /* UTC_RELEASE */
|
||||
#undef CONFIG_DEVFS_FS
|
||||
#endif /* LINUX_2_6 */
|
||||
--- a/src/mps/drv_mps_vmmc_common.c
|
||||
+++ b/src/mps/drv_mps_vmmc_common.c
|
||||
@@ -22,7 +22,11 @@
|
||||
#undef USE_PLAIN_VOICE_FIRMWARE
|
||||
#undef PRINT_ON_ERR_INTERRUPT
|
||||
#undef FAIL_ON_ERR_INTERRUPT
|
||||
-#include <generated/autoconf.h>
|
||||
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
|
||||
+#include <linux/utsrelease.h>
|
||||
+#else
|
||||
+#include <generated/utsrelease.h>
|
||||
+#endif
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
@@ -47,8 +51,19 @@
|
||||
# define ifx_gptu_timer_free lq_free_timer
|
||||
|
||||
|
||||
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
|
||||
# define bsp_mask_and_ack_irq ltq_mask_and_ack_irq
|
||||
#else
|
||||
+extern void ltq_mask_and_ack_irq(struct irq_data *d);
|
||||
+static void inline bsp_mask_and_ack_irq(int x)
|
||||
+{
|
||||
+ struct irq_data d;
|
||||
+ d.irq = x;
|
||||
+ ltq_mask_and_ack_irq(&d);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+#else
|
||||
# include <asm/ifx/ifx_regs.h>
|
||||
# include <asm/ifx/ifx_gptu.h>
|
||||
#endif
|
||||
@@ -107,7 +122,9 @@
|
||||
extern mps_mbx_dev *ifx_mps_get_device (mps_devices type);
|
||||
|
||||
#ifdef LINUX_2_6
|
||||
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39))
|
||||
extern IFX_void_t bsp_mask_and_ack_irq (IFX_uint32_t irq_nr);
|
||||
+#endif
|
||||
|
||||
#else /* */
|
||||
extern IFX_void_t mask_and_ack_danube_irq (IFX_uint32_t irq_nr);
|
||||
--- a/src/mps/drv_mps_vmmc_danube.c
|
||||
+++ b/src/mps/drv_mps_vmmc_danube.c
|
||||
@@ -16,11 +16,16 @@
|
||||
/* ============================= */
|
||||
/* Includes */
|
||||
/* ============================= */
|
||||
+#include "linux/version.h"
|
||||
#include "drv_config.h"
|
||||
|
||||
#ifdef SYSTEM_DANUBE /* defined in drv_mps_vmmc_config.h */
|
||||
|
||||
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33))
|
||||
+#include <linux/autoconf.h>
|
||||
+#else
|
||||
#include <generated/autoconf.h>
|
||||
+#endif
|
||||
|
||||
/* lib_ifxos headers */
|
||||
#include "ifx_types.h"
|
||||
@@ -39,6 +44,7 @@
|
||||
# include <linux/dma-mapping.h>
|
||||
|
||||
|
||||
+#define LQ_RCU_BASE_ADDR (KSEG1 + LTQ_RCU_BASE_ADDR)
|
||||
# define LQ_RCU_RST ((u32 *)(LQ_RCU_BASE_ADDR + 0x0010))
|
||||
#define IFX_RCU_RST_REQ_CPU1 (1 << 3)
|
||||
# define IFX_RCU_RST_REQ LQ_RCU_RST
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
--- a/include/linux/atm.h
|
||||
+++ b/include/linux/atm.h
|
||||
@@ -139,6 +139,9 @@ struct atm_trafprm {
|
||||
int min_pcr; /* minimum PCR in cells per second */
|
||||
int max_cdv; /* maximum CDV in microseconds */
|
||||
int max_sdu; /* maximum SDU in bytes */
|
||||
+ int scr; /* sustained rate in cells per second */
|
||||
+ int mbs; /* maximum burst size (MBS) in cells */
|
||||
+ int cdv; /* Cell delay varition */
|
||||
/* extra params for ABR */
|
||||
unsigned int icr; /* Initial Cell Rate (24-bit) */
|
||||
unsigned int tbe; /* Transient Buffer Exposure (24-bit) */
|
|
@ -0,0 +1,12 @@
|
|||
--- a/include/linux/atm.h
|
||||
+++ b/include/linux/atm.h
|
||||
@@ -139,6 +139,9 @@ struct atm_trafprm {
|
||||
int min_pcr; /* minimum PCR in cells per second */
|
||||
int max_cdv; /* maximum CDV in microseconds */
|
||||
int max_sdu; /* maximum SDU in bytes */
|
||||
+ int scr; /* sustained rate in cells per second */
|
||||
+ int mbs; /* maximum burst size (MBS) in cells */
|
||||
+ int cdv; /* Cell delay varition */
|
||||
/* extra params for ABR */
|
||||
unsigned int icr; /* Initial Cell Rate (24-bit) */
|
||||
unsigned int tbe; /* Transient Buffer Exposure (24-bit) */
|
|
@ -10,9 +10,10 @@ ARCH:=mips
|
|||
BOARD:=lantiq
|
||||
BOARDNAME:=Lantiq GPON/XWAY
|
||||
FEATURES:=squashfs jffs2
|
||||
SUBTARGETS:=falcon xway
|
||||
SUBTARGETS:=falcon xway ase
|
||||
|
||||
LINUX_VERSION:=2.6.37.6
|
||||
LINUX_VERSION:=2.6.39
|
||||
#LINUX_VERSION:=2.6.32.33
|
||||
|
||||
CFLAGS=-Os -pipe -mips32r2 -mtune=mips32r2 -fno-caller-saves
|
||||
|
||||
|
|
15
target/linux/lantiq/ase/config-2.6.32
Normal file
15
target/linux/lantiq/ase/config-2.6.32
Normal file
|
@ -0,0 +1,15 @@
|
|||
CONFIG_CRYPTO_ALGAPI=y
|
||||
CONFIG_CRYPTO_ALGAPI2=y
|
||||
# CONFIG_DM9000 is not set
|
||||
CONFIG_INPUT=y
|
||||
CONFIG_INPUT_EVDEV=y
|
||||
# CONFIG_INPUT_GPIO_BUTTONS is not set
|
||||
CONFIG_INPUT_POLLDEV=y
|
||||
# CONFIG_ISDN is not set
|
||||
CONFIG_LANTIQ_ETOP=y
|
||||
CONFIG_LANTIQ_MACH_EASY50601=y
|
||||
CONFIG_SOC_AMAZON_SE=y
|
||||
# CONFIG_SOC_FALCON is not set
|
||||
CONFIG_SOC_TYPE_XWAY=y
|
||||
# CONFIG_SOC_XWAY is not set
|
||||
# CONFIG_I2C_DESIGNWARE is not set
|
39
target/linux/lantiq/ase/config-default
Normal file
39
target/linux/lantiq/ase/config-default
Normal file
|
@ -0,0 +1,39 @@
|
|||
# CONFIG_ARCH_DMA_ADDR_T_64BIT is not set
|
||||
# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
|
||||
# CONFIG_ATH79 is not set
|
||||
CONFIG_CRYPTO_ALGAPI=y
|
||||
CONFIG_CRYPTO_ALGAPI2=y
|
||||
CONFIG_GENERIC_ATOMIC64=y
|
||||
CONFIG_GENERIC_IRQ_SHOW=y
|
||||
CONFIG_HAVE_ARCH_JUMP_LABEL=y
|
||||
CONFIG_HAVE_C_RECORDMCOUNT=y
|
||||
CONFIG_HAVE_DMA_API_DEBUG=y
|
||||
CONFIG_HAVE_DMA_ATTRS=y
|
||||
CONFIG_HAVE_DYNAMIC_FTRACE=y
|
||||
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
|
||||
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
|
||||
CONFIG_HAVE_FUNCTION_TRACER=y
|
||||
CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
|
||||
CONFIG_HAVE_GENERIC_HARDIRQS=y
|
||||
CONFIG_HAVE_IRQ_WORK=y
|
||||
CONFIG_HAVE_PERF_EVENTS=y
|
||||
CONFIG_INPUT=y
|
||||
CONFIG_INPUT_EVDEV=y
|
||||
# CONFIG_INPUT_GPIO_BUTTONS is not set
|
||||
CONFIG_INPUT_POLLDEV=y
|
||||
# CONFIG_ISDN is not set
|
||||
CONFIG_LANTIQ_ETOP=y
|
||||
CONFIG_LANTIQ_MACH_EASY50601=y
|
||||
CONFIG_MACH_NO_WESTBRIDGE=y
|
||||
# CONFIG_MINIX_FS_NATIVE_ENDIAN is not set
|
||||
# CONFIG_MTD_LATCH_ADDR is not set
|
||||
CONFIG_NEED_DMA_MAP_STATE=y
|
||||
CONFIG_NEED_PER_CPU_KM=y
|
||||
CONFIG_PERF_USE_VMALLOC=y
|
||||
# CONFIG_PREEMPT_RCU is not set
|
||||
# CONFIG_QUOTACTL is not set
|
||||
CONFIG_SOC_AMAZON_SE=y
|
||||
# CONFIG_SOC_FALCON is not set
|
||||
CONFIG_SOC_TYPE_XWAY=y
|
||||
# CONFIG_SOC_XWAY is not set
|
||||
CONFIG_XZ_DEC=y
|
6
target/linux/lantiq/ase/profiles/000-generic.mk
Normal file
6
target/linux/lantiq/ase/profiles/000-generic.mk
Normal file
|
@ -0,0 +1,6 @@
|
|||
define Profile/Generic
|
||||
NAME:=Generic - all boards
|
||||
PACKAGES:=kmod-leds-gpio button-hotplug
|
||||
endef
|
||||
|
||||
$(eval $(call Profile,Generic))
|
10
target/linux/lantiq/ase/profiles/001-lantiq.mk
Normal file
10
target/linux/lantiq/ase/profiles/001-lantiq.mk
Normal file
|
@ -0,0 +1,10 @@
|
|||
define Profile/EASY50601
|
||||
NAME:=EASY50601
|
||||
PACKAGES:= kmod-usb-core kmod-usb-dwc-otg kmod-leds-gpio
|
||||
endef
|
||||
|
||||
define Profile/EASY50601/Description
|
||||
Lantiq EASY50601 evalkit
|
||||
endef
|
||||
|
||||
$(eval $(call Profile,EASY50601))
|
10
target/linux/lantiq/ase/target.mk
Normal file
10
target/linux/lantiq/ase/target.mk
Normal file
|
@ -0,0 +1,10 @@
|
|||
ARCH:=mips
|
||||
SUBTARGET:=ase
|
||||
BOARDNAME:=Amazon-SE
|
||||
FEATURES:=squashfs jffs2 atm
|
||||
|
||||
DEFAULT_PACKAGES+=kmod-pppoa ppp-mod-pppoa linux-atm atm-tools br2684ctl kmod-ltq-dsl ltq-dsl-app
|
||||
|
||||
define Target/Description
|
||||
Lantiq ASE
|
||||
endef
|
|
@ -1,4 +1,4 @@
|
|||
::sysinit:/etc/init.d/rcS S boot
|
||||
::shutdown:/etc/init.d/rcS K stop
|
||||
ttyS0::askfirst:/bin/ash --login
|
||||
ttyS1::askfirst:/bin/ash --login
|
||||
ttyLTQ0::askfirst:/bin/ash --login
|
||||
ttyLTQ1::askfirst:/bin/ash --login
|
||||
|
|
149
target/linux/lantiq/config-2.6.32
Normal file
149
target/linux/lantiq/config-2.6.32
Normal file
|
@ -0,0 +1,149 @@
|
|||
CONFIG_32BIT=y
|
||||
# CONFIG_64BIT is not set
|
||||
# CONFIG_ALCHEMY_GPIO_INDIRECT is not set
|
||||
# CONFIG_AR7 is not set
|
||||
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
|
||||
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
|
||||
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
|
||||
CONFIG_ARCH_POPULATES_NODE_MAP=y
|
||||
CONFIG_ARCH_REQUIRE_GPIOLIB=y
|
||||
# CONFIG_ARCH_SUPPORTS_MSI is not set
|
||||
CONFIG_ARCH_SUPPORTS_OPROFILE=y
|
||||
CONFIG_ARCH_SUSPEND_POSSIBLE=y
|
||||
# CONFIG_BCM47XX is not set
|
||||
# CONFIG_BCM63XX is not set
|
||||
CONFIG_BITREVERSE=y
|
||||
CONFIG_BOOT_RAW=y
|
||||
# CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set
|
||||
# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set
|
||||
CONFIG_CEVT_R4K=y
|
||||
CONFIG_CEVT_R4K_LIB=y
|
||||
CONFIG_CFG80211_DEFAULT_PS_VALUE=0
|
||||
CONFIG_CPU_BIG_ENDIAN=y
|
||||
# CONFIG_CPU_CAVIUM_OCTEON is not set
|
||||
CONFIG_CPU_HAS_PREFETCH=y
|
||||
CONFIG_CPU_HAS_SYNC=y
|
||||
# CONFIG_CPU_LITTLE_ENDIAN is not set
|
||||
# CONFIG_CPU_LOONGSON2E is not set
|
||||
CONFIG_CPU_MIPS32=y
|
||||
# CONFIG_CPU_MIPS32_R1 is not set
|
||||
CONFIG_CPU_MIPS32_R2=y
|
||||
# CONFIG_CPU_MIPS64_R1 is not set
|
||||
# CONFIG_CPU_MIPS64_R2 is not set
|
||||
CONFIG_CPU_MIPSR2=y
|
||||
# CONFIG_CPU_NEVADA is not set
|
||||
# CONFIG_CPU_R10000 is not set
|
||||
# CONFIG_CPU_R3000 is not set
|
||||
# CONFIG_CPU_R4300 is not set
|
||||
# CONFIG_CPU_R4X00 is not set
|
||||
# CONFIG_CPU_R5000 is not set
|
||||
# CONFIG_CPU_R5432 is not set
|
||||
# CONFIG_CPU_R5500 is not set
|
||||
# CONFIG_CPU_R6000 is not set
|
||||
# CONFIG_CPU_R8000 is not set
|
||||
# CONFIG_CPU_RM7000 is not set
|
||||
# CONFIG_CPU_RM9000 is not set
|
||||
# CONFIG_CPU_SB1 is not set
|
||||
CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y
|
||||
CONFIG_CPU_SUPPORTS_HIGHMEM=y
|
||||
# CONFIG_CPU_TX39XX is not set
|
||||
# CONFIG_CPU_TX49XX is not set
|
||||
# CONFIG_CPU_VR41XX is not set
|
||||
CONFIG_CSRC_R4K=y
|
||||
CONFIG_CSRC_R4K_LIB=y
|
||||
CONFIG_DECOMPRESS_LZMA=y
|
||||
CONFIG_DMA_NEED_PCI_MAP_STATE=y
|
||||
CONFIG_DMA_NONCOHERENT=y
|
||||
CONFIG_EARLY_PRINTK=y
|
||||
# CONFIG_FSNOTIFY is not set
|
||||
CONFIG_GENERIC_CLOCKEVENTS=y
|
||||
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
|
||||
CONFIG_GENERIC_CMOS_UPDATE=y
|
||||
CONFIG_GENERIC_FIND_LAST_BIT=y
|
||||
CONFIG_GENERIC_FIND_NEXT_BIT=y
|
||||
CONFIG_GENERIC_GPIO=y
|
||||
CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
|
||||
CONFIG_GPIOLIB=y
|
||||
CONFIG_GPIO_SYSFS=y
|
||||
CONFIG_HARDWARE_WATCHPOINTS=y
|
||||
CONFIG_HAS_DMA=y
|
||||
CONFIG_HAS_IOMEM=y
|
||||
CONFIG_HAS_IOPORT=y
|
||||
CONFIG_HAVE_ARCH_KGDB=y
|
||||
CONFIG_HAVE_CLK=y
|
||||
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
|
||||
CONFIG_HAVE_IDE=y
|
||||
CONFIG_HAVE_OPROFILE=y
|
||||
CONFIG_HW_RANDOM=y
|
||||
CONFIG_HZ=250
|
||||
# CONFIG_HZ_100 is not set
|
||||
CONFIG_HZ_250=y
|
||||
CONFIG_IFX_UDP_REDIRECT=y
|
||||
CONFIG_IMAGE_CMDLINE_HACK=y
|
||||
CONFIG_INITRAMFS_SOURCE=""
|
||||
CONFIG_IRQ_CPU=y
|
||||
CONFIG_LANTIQ=y
|
||||
CONFIG_LANTIQ_WDT=y
|
||||
CONFIG_LEDS_GPIO=y
|
||||
# CONFIG_MACH_ALCHEMY is not set
|
||||
# CONFIG_MACH_DECSTATION is not set
|
||||
# CONFIG_MACH_JAZZ is not set
|
||||
# CONFIG_MACH_LOONGSON is not set
|
||||
# CONFIG_MACH_TX39XX is not set
|
||||
# CONFIG_MACH_TX49XX is not set
|
||||
# CONFIG_MACH_VR41XX is not set
|
||||
# CONFIG_MIKROTIK_RB532 is not set
|
||||
CONFIG_MIPS=y
|
||||
# CONFIG_MIPS_COBALT is not set
|
||||
CONFIG_MIPS_L1_CACHE_SHIFT=5
|
||||
CONFIG_MIPS_MACHINE=y
|
||||
# CONFIG_MIPS_MALTA is not set
|
||||
CONFIG_MIPS_MT_DISABLED=y
|
||||
# CONFIG_MIPS_MT_SMP is not set
|
||||
# CONFIG_MIPS_MT_SMTC is not set
|
||||
# CONFIG_MIPS_SIM is not set
|
||||
# CONFIG_MIPS_VPE_LOADER is not set
|
||||
CONFIG_MTD_CFI_ADV_OPTIONS=y
|
||||
CONFIG_MTD_CFI_GEOMETRY=y
|
||||
CONFIG_MTD_CMDLINE_PARTS=y
|
||||
CONFIG_MTD_LANTIQ=y
|
||||
CONFIG_MTD_UIMAGE_SPLIT=y
|
||||
CONFIG_NLS=y
|
||||
# CONFIG_NO_IOPORT is not set
|
||||
# CONFIG_NXP_STB220 is not set
|
||||
# CONFIG_NXP_STB225 is not set
|
||||
CONFIG_PAGEFLAGS_EXTENDED=y
|
||||
CONFIG_PHYLIB=y
|
||||
# CONFIG_PMC_MSP is not set
|
||||
# CONFIG_PMC_YOSEMITE is not set
|
||||
# CONFIG_PNX8550_JBS is not set
|
||||
# CONFIG_PNX8550_STB810 is not set
|
||||
CONFIG_SCHED_OMIT_FRAME_POINTER=y
|
||||
# CONFIG_SCSI_DMA is not set
|
||||
# CONFIG_SERIAL_8250 is not set
|
||||
CONFIG_SERIAL_LANTIQ=y
|
||||
# CONFIG_SGI_IP22 is not set
|
||||
# CONFIG_SGI_IP27 is not set
|
||||
# CONFIG_SGI_IP28 is not set
|
||||
# CONFIG_SGI_IP32 is not set
|
||||
# CONFIG_SIBYTE_BIGSUR is not set
|
||||
# CONFIG_SIBYTE_CARMEL is not set
|
||||
# CONFIG_SIBYTE_CRHINE is not set
|
||||
# CONFIG_SIBYTE_CRHONE is not set
|
||||
# CONFIG_SIBYTE_LITTLESUR is not set
|
||||
# CONFIG_SIBYTE_RHONE is not set
|
||||
# CONFIG_SIBYTE_SENTOSA is not set
|
||||
# CONFIG_SIBYTE_SWARM is not set
|
||||
CONFIG_SWAP_IO_SPACE=y
|
||||
CONFIG_SWCONFIG=y
|
||||
CONFIG_SYS_HAS_CPU_MIPS32_R1=y
|
||||
CONFIG_SYS_HAS_CPU_MIPS32_R2=y
|
||||
CONFIG_SYS_HAS_EARLY_PRINTK=y
|
||||
CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
|
||||
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
|
||||
CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
|
||||
CONFIG_SYS_SUPPORTS_MULTITHREADING=y
|
||||
CONFIG_TRAD_SIGNALS=y
|
||||
# CONFIG_TREE_PREEMPT_RCU is not set
|
||||
CONFIG_TREE_RCU=y
|
||||
CONFIG_ZONE_DMA_FLAG=0
|
|
@ -5,28 +5,26 @@ CONFIG_32BIT=y
|
|||
# CONFIG_ARCH_HAS_ILOG2_U32 is not set
|
||||
# CONFIG_ARCH_HAS_ILOG2_U64 is not set
|
||||
CONFIG_ARCH_HIBERNATION_POSSIBLE=y
|
||||
# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
|
||||
CONFIG_ARCH_POPULATES_NODE_MAP=y
|
||||
CONFIG_ARCH_REQUIRE_GPIOLIB=y
|
||||
# CONFIG_ARCH_SUPPORTS_MSI is not set
|
||||
CONFIG_ARCH_SUPPORTS_OPROFILE=y
|
||||
CONFIG_ARCH_SUSPEND_POSSIBLE=y
|
||||
# CONFIG_AUTO_IRQ_AFFINITY is not set
|
||||
# CONFIG_BCM47XX is not set
|
||||
# CONFIG_BCM63XX is not set
|
||||
CONFIG_BITREVERSE=y
|
||||
CONFIG_BKL=y
|
||||
CONFIG_BOOT_RAW=y
|
||||
# CONFIG_CAVIUM_OCTEON_REFERENCE_BOARD is not set
|
||||
# CONFIG_CAVIUM_OCTEON_SIMULATOR is not set
|
||||
CONFIG_CEVT_R4K=y
|
||||
CONFIG_CEVT_R4K_LIB=y
|
||||
CONFIG_CFG80211_DEFAULT_PS_VALUE=0
|
||||
CONFIG_CPU_BIG_ENDIAN=y
|
||||
# CONFIG_CPU_CAVIUM_OCTEON is not set
|
||||
CONFIG_CPU_HAS_PREFETCH=y
|
||||
CONFIG_CPU_HAS_SYNC=y
|
||||
# CONFIG_CPU_LITTLE_ENDIAN is not set
|
||||
# CONFIG_CPU_LOONGSON2E is not set
|
||||
# CONFIG_CPU_LOONGSON2F is not set
|
||||
CONFIG_CPU_MIPS32=y
|
||||
# CONFIG_CPU_MIPS32_R1 is not set
|
||||
CONFIG_CPU_MIPS32_R2=y
|
||||
|
@ -54,63 +52,43 @@ CONFIG_CPU_SUPPORTS_HIGHMEM=y
|
|||
CONFIG_CSRC_R4K=y
|
||||
CONFIG_CSRC_R4K_LIB=y
|
||||
CONFIG_DECOMPRESS_LZMA=y
|
||||
CONFIG_DEVPORT=y
|
||||
# CONFIG_DM9000 is not set
|
||||
CONFIG_DMA_NEED_PCI_MAP_STATE=y
|
||||
CONFIG_DMA_NONCOHERENT=y
|
||||
CONFIG_EARLY_PRINTK=y
|
||||
# CONFIG_FSNOTIFY is not set
|
||||
CONFIG_GENERIC_ATOMIC64=y
|
||||
CONFIG_GENERIC_CLOCKEVENTS=y
|
||||
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
|
||||
CONFIG_GENERIC_CMOS_UPDATE=y
|
||||
CONFIG_GENERIC_FIND_LAST_BIT=y
|
||||
CONFIG_GENERIC_FIND_NEXT_BIT=y
|
||||
CONFIG_GENERIC_GPIO=y
|
||||
# CONFIG_GENERIC_HARDIRQS_NO_DEPRECATED is not set
|
||||
CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y
|
||||
# CONFIG_GENERIC_PENDING_IRQ is not set
|
||||
CONFIG_GPIOLIB=y
|
||||
CONFIG_GPIO_SYSFS=y
|
||||
# CONFIG_HARDIRQS_SW_RESEND is not set
|
||||
CONFIG_HARDWARE_WATCHPOINTS=y
|
||||
CONFIG_HAS_DMA=y
|
||||
CONFIG_HAS_IOMEM=y
|
||||
CONFIG_HAS_IOPORT=y
|
||||
CONFIG_HAVE_ARCH_KGDB=y
|
||||
CONFIG_HAVE_C_RECORDMCOUNT=y
|
||||
CONFIG_HAVE_DMA_API_DEBUG=y
|
||||
CONFIG_HAVE_DMA_ATTRS=y
|
||||
CONFIG_HAVE_DYNAMIC_FTRACE=y
|
||||
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
|
||||
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
|
||||
CONFIG_HAVE_FUNCTION_TRACER=y
|
||||
CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
|
||||
CONFIG_HAVE_CLK=y
|
||||
CONFIG_HAVE_GENERIC_DMA_COHERENT=y
|
||||
CONFIG_HAVE_GENERIC_HARDIRQS=y
|
||||
# CONFIG_HAVE_IDE is not set
|
||||
CONFIG_HAVE_IDE=y
|
||||
CONFIG_HAVE_OPROFILE=y
|
||||
CONFIG_HAVE_PERF_EVENTS=y
|
||||
# CONFIG_HAVE_SPARSE_IRQ is not set
|
||||
CONFIG_HW_RANDOM=y
|
||||
CONFIG_HZ=250
|
||||
# CONFIG_HZ_100 is not set
|
||||
CONFIG_HZ_250=y
|
||||
# CONFIG_I2C_FALCON is not set
|
||||
CONFIG_IFX_UDP_REDIRECT=y
|
||||
CONFIG_IMAGE_CMDLINE_HACK=y
|
||||
CONFIG_INITRAMFS_SOURCE=""
|
||||
CONFIG_IRQ_CPU=y
|
||||
# CONFIG_IRQ_PER_CPU is not set
|
||||
CONFIG_LANTIQ=y
|
||||
CONFIG_LANTIQ_WDT=y
|
||||
CONFIG_LEDS_GPIO=y
|
||||
CONFIG_LOONGSON_UART_BASE=y
|
||||
# CONFIG_MACH_ALCHEMY is not set
|
||||
# CONFIG_MACH_DECSTATION is not set
|
||||
# CONFIG_MACH_JAZZ is not set
|
||||
# CONFIG_MACH_LOONGSON is not set
|
||||
CONFIG_MACH_NO_WESTBRIDGE=y
|
||||
# CONFIG_MACH_TX39XX is not set
|
||||
# CONFIG_MACH_TX49XX is not set
|
||||
# CONFIG_MACH_VR41XX is not set
|
||||
|
@ -130,28 +108,19 @@ CONFIG_MTD_CFI_GEOMETRY=y
|
|||
CONFIG_MTD_CMDLINE_PARTS=y
|
||||
CONFIG_MTD_LANTIQ=y
|
||||
CONFIG_MTD_UIMAGE_SPLIT=y
|
||||
CONFIG_NEED_DMA_MAP_STATE=y
|
||||
CONFIG_NEED_PER_CPU_KM=y
|
||||
CONFIG_NLS=y
|
||||
# CONFIG_NO_IOPORT is not set
|
||||
# CONFIG_NXP_STB220 is not set
|
||||
# CONFIG_NXP_STB225 is not set
|
||||
CONFIG_PAGEFLAGS_EXTENDED=y
|
||||
CONFIG_PCI=y
|
||||
CONFIG_PCI_DOMAINS=y
|
||||
CONFIG_PERF_USE_VMALLOC=y
|
||||
CONFIG_PHYLIB=y
|
||||
# CONFIG_PMC_MSP is not set
|
||||
# CONFIG_PMC_YOSEMITE is not set
|
||||
# CONFIG_PNX8550_JBS is not set
|
||||
# CONFIG_PNX8550_STB810 is not set
|
||||
# CONFIG_POWERTV is not set
|
||||
# CONFIG_PREEMPT_RCU is not set
|
||||
# CONFIG_QUOTACTL is not set
|
||||
CONFIG_SCHED_OMIT_FRAME_POINTER=y
|
||||
# CONFIG_SCSI_DMA is not set
|
||||
# CONFIG_SERIAL_8250 is not set
|
||||
# CONFIG_SERIAL_8250_EXTENDED is not set
|
||||
CONFIG_SERIAL_LANTIQ=y
|
||||
# CONFIG_SGI_IP22 is not set
|
||||
# CONFIG_SGI_IP27 is not set
|
||||
|
@ -165,7 +134,6 @@ CONFIG_SERIAL_LANTIQ=y
|
|||
# CONFIG_SIBYTE_RHONE is not set
|
||||
# CONFIG_SIBYTE_SENTOSA is not set
|
||||
# CONFIG_SIBYTE_SWARM is not set
|
||||
CONFIG_SOC_LANTIQ=y
|
||||
CONFIG_SWAP_IO_SPACE=y
|
||||
CONFIG_SWCONFIG=y
|
||||
CONFIG_SYS_HAS_CPU_MIPS32_R1=y
|
||||
|
@ -175,8 +143,6 @@ CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y
|
|||
CONFIG_SYS_SUPPORTS_ARBIT_HZ=y
|
||||
CONFIG_SYS_SUPPORTS_BIG_ENDIAN=y
|
||||
CONFIG_SYS_SUPPORTS_MULTITHREADING=y
|
||||
# CONFIG_TC35815 is not set
|
||||
CONFIG_TINY_RCU=y
|
||||
CONFIG_TRAD_SIGNALS=y
|
||||
# CONFIG_TREE_PREEMPT_RCU is not set
|
||||
CONFIG_TREE_RCU=y
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
#!/usr/bin/python
|
||||
from sys import stdin, stdout
|
||||
while True:
|
||||
c = stdin.read(2)
|
||||
if len(c) < 2:
|
||||
break
|
||||
n1, n2 = ord(c[0]), ord(c[1])
|
||||
stdout.write(chr(((n2 & 15) << 4) + ((n2 & 240) >> 4)))
|
||||
stdout.write(chr(((n1 & 15) << 4) + ((n1 & 240) >> 4)))
|
|
@ -1,44 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
DIR="$1/"
|
||||
FILE="$1/$2"
|
||||
|
||||
echo "This tool downloads the arcor a800 firmware release and extracts the voip firmware for the danube."
|
||||
echo "Please only do so if it is legal in your country"
|
||||
|
||||
[ ! -f ${FILE} ] && {
|
||||
echo ${FILE} is missing
|
||||
exit 1
|
||||
}
|
||||
|
||||
[ -f ${DIR}/ifxmips_fw_decodev2.tar.bz2 -a ! -f ${DIR}voip_coef.bin ] && {
|
||||
[ ! -f ${DIR}decode_ifx_fw && -f ${DIR}ifxmips_fw_decodev2.tar.bz2 ] && {
|
||||
tar xjf ${DIR}ifxmips_fw_decodev2.tar.bz2 ifxmips_fw_decode/decode.c -O > ${DIR}decode.c
|
||||
gcc -o ${DIR}decode_ifx_fw ${DIR}decode.c
|
||||
}
|
||||
[ ! -f ${DIR}decode_ifx_fw ] && {
|
||||
[ ! -f ${DIR}voip_coef.lzma ] && {
|
||||
${DIR}decode_ifx_fw $FILE ${DIR}voip_coef.lzma
|
||||
}
|
||||
lzma d ${DIR}voip_coef.lzma ${DIR}voip_coef.bin
|
||||
}
|
||||
}
|
||||
[ ! -f ${DIR}dsl_a.bin ] && {
|
||||
dd if=${FILE} of=${DIR}dsl1.lzma bs=1 skip=2168832 count=150724
|
||||
lzma d ${DIR}dsl2.lzma ${DIR}dsl_a.bin
|
||||
}
|
||||
|
||||
[ ! -f ${DIR}dsl_b.bin ] && {
|
||||
dd if=${FILE} of=${DIR}dsl2.lzma bs=1 skip=2320384 count=148343
|
||||
lzma d ${DIR}dsl1.lzma ${DIR}dsl_b.bin
|
||||
}
|
||||
|
||||
[ ! -f ${DIR}voip.bin ] && {
|
||||
dd if=${FILE} of=${DIR}voip.lzma bs=1 skip=2468864 count=452105
|
||||
lzma d ${DIR}voip.lzma ${DIR}voip.bin
|
||||
}
|
||||
exit 0
|
||||
|
||||
# get lzma offsets
|
||||
# hexdump -C arcor_A800_452CPW_FW_1.02.206\(20081201\).bin | grep "5d 00 00 80"
|
||||
# hexdump -C arcor_A800_452CPW_FW_1.02.206\(20081201\).bin | grep "00 d5 08 00"
|
33
target/linux/lantiq/falcon/config-2.6.32
Normal file
33
target/linux/lantiq/falcon/config-2.6.32
Normal file
|
@ -0,0 +1,33 @@
|
|||
CONFIG_CPU_MIPSR2_IRQ_EI=y
|
||||
CONFIG_CPU_MIPSR2_IRQ_VI=y
|
||||
# CONFIG_CRYPTO is not set
|
||||
CONFIG_DM9000=y
|
||||
CONFIG_DM9000_DEBUGLEVEL=4
|
||||
CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
|
||||
CONFIG_I2C=y
|
||||
CONFIG_I2C_BOARDINFO=y
|
||||
# CONFIG_I2C_DESIGNWARE is not set
|
||||
CONFIG_I2C_FALCON=y
|
||||
CONFIG_IFX_VPE_CACHE_SPLIT=y
|
||||
CONFIG_IFX_VPE_EXT=y
|
||||
CONFIG_LANTIQ_MACH_95C3AM1=y
|
||||
CONFIG_LANTIQ_MACH_EASY98000=y
|
||||
CONFIG_LANTIQ_MACH_EASY98020=y
|
||||
CONFIG_M25PXX_USE_FAST_READ=y
|
||||
CONFIG_MIPS_MT=y
|
||||
# CONFIG_MIPS_VPE_APSP_API is not set
|
||||
CONFIG_MIPS_VPE_LOADER=y
|
||||
CONFIG_MIPS_VPE_LOADER_TOM=y
|
||||
CONFIG_MTD_M25P80=y
|
||||
CONFIG_MTSCHED=y
|
||||
# CONFIG_PERFCTRS is not set
|
||||
# CONFIG_SOC_AMAZON_SE is not set
|
||||
CONFIG_SOC_FALCON=y
|
||||
# CONFIG_SOC_TYPE_XWAY is not set
|
||||
# CONFIG_SOC_XWAY is not set
|
||||
CONFIG_SPI=y
|
||||
# CONFIG_SPI_BITBANG is not set
|
||||
CONFIG_SPI_FALCON=y
|
||||
# CONFIG_SPI_GPIO is not set
|
||||
CONFIG_SPI_MASTER=y
|
||||
# CONFIG_SPI_SPIDEV is not set
|
|
@ -1,31 +1,63 @@
|
|||
# CONFIG_ALTERA_STAPL is not set
|
||||
# CONFIG_ARCH_DMA_ADDR_T_64BIT is not set
|
||||
# CONFIG_ARCH_PHYS_ADDR_T_64BIT is not set
|
||||
# CONFIG_ATH79 is not set
|
||||
CONFIG_CPU_MIPSR2_IRQ_EI=y
|
||||
CONFIG_CPU_MIPSR2_IRQ_VI=y
|
||||
# CONFIG_CRYPTO is not set
|
||||
CONFIG_DM9000=y
|
||||
CONFIG_DM9000_DEBUGLEVEL=4
|
||||
CONFIG_DM9000_FORCE_SIMPLE_PHY_POLL=y
|
||||
CONFIG_HAVE_IDE=y
|
||||
CONFIG_HW_HAS_PCI=y
|
||||
CONFIG_GENERIC_ATOMIC64=y
|
||||
CONFIG_GENERIC_IRQ_SHOW=y
|
||||
CONFIG_HAVE_ARCH_JUMP_LABEL=y
|
||||
CONFIG_HAVE_C_RECORDMCOUNT=y
|
||||
CONFIG_HAVE_DMA_API_DEBUG=y
|
||||
CONFIG_HAVE_DMA_ATTRS=y
|
||||
CONFIG_HAVE_DYNAMIC_FTRACE=y
|
||||
CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y
|
||||
CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y
|
||||
CONFIG_HAVE_FUNCTION_TRACER=y
|
||||
CONFIG_HAVE_FUNCTION_TRACE_MCOUNT_TEST=y
|
||||
CONFIG_HAVE_GENERIC_HARDIRQS=y
|
||||
CONFIG_HAVE_IRQ_WORK=y
|
||||
CONFIG_HAVE_PERF_EVENTS=y
|
||||
CONFIG_I2C=y
|
||||
CONFIG_I2C_BOARDINFO=y
|
||||
CONFIG_I2C_FALCON=y
|
||||
# CONFIG_I2C_PXA_PCI is not set
|
||||
CONFIG_IFX_VPE_CACHE_SPLIT=y
|
||||
CONFIG_IFX_VPE_EXT=y
|
||||
CONFIG_LANTIQ_MACH_95C3AM1=y
|
||||
CONFIG_LANTIQ_MACH_EASY98000=y
|
||||
CONFIG_LANTIQ_MACH_EASY98020=y
|
||||
CONFIG_LANTIQ_PROM_ASC0=y
|
||||
# CONFIG_LANTIQ_PROM_ASC1 is not set
|
||||
# CONFIG_LEDS_LM3530 is not set
|
||||
CONFIG_M25PXX_USE_FAST_READ=y
|
||||
CONFIG_MACH_NO_WESTBRIDGE=y
|
||||
# CONFIG_MFD_MAX8997 is not set
|
||||
# CONFIG_MFD_WL1273_CORE is not set
|
||||
# CONFIG_MINIX_FS_NATIVE_ENDIAN is not set
|
||||
CONFIG_MIPS_MT=y
|
||||
# CONFIG_MIPS_VPE_APSP_API is not set
|
||||
CONFIG_MIPS_VPE_LOADER=y
|
||||
CONFIG_MIPS_VPE_LOADER_TOM=y
|
||||
# CONFIG_MTD_LATCH_ADDR is not set
|
||||
CONFIG_MTD_M25P80=y
|
||||
CONFIG_MTSCHED=y
|
||||
# CONFIG_PCI is not set
|
||||
CONFIG_NEED_DMA_MAP_STATE=y
|
||||
CONFIG_NEED_PER_CPU_KM=y
|
||||
# CONFIG_PERFCTRS is not set
|
||||
CONFIG_SOC_LANTIQ_FALCON=y
|
||||
# CONFIG_SOC_LANTIQ_XWAY is not set
|
||||
CONFIG_PERF_USE_VMALLOC=y
|
||||
# CONFIG_PREEMPT_RCU is not set
|
||||
# CONFIG_QUOTACTL is not set
|
||||
# CONFIG_SOC_AMAZON_SE is not set
|
||||
CONFIG_SOC_FALCON=y
|
||||
# CONFIG_SOC_TYPE_XWAY is not set
|
||||
# CONFIG_SOC_XWAY is not set
|
||||
CONFIG_SPI=y
|
||||
# CONFIG_SPI_BITBANG is not set
|
||||
CONFIG_SPI_FALCON=y
|
||||
# CONFIG_SPI_GPIO is not set
|
||||
CONFIG_SPI_MASTER=y
|
||||
# CONFIG_TPS6105X is not set
|
||||
CONFIG_XZ_DEC=y
|
||||
|
|
|
@ -9,8 +9,9 @@ include $(INCLUDE_DIR)/image.mk
|
|||
|
||||
JFFS2_BLOCKSIZE = 64k 128k 256k
|
||||
|
||||
xway_cmdline=-console=ttyS1,115200 rootfstype=squashfs,jffs2
|
||||
falcon_cmdline=-console=ttyS0,115200 rootfstype=squashfs,jffs2
|
||||
ase_cmdline=-console=ttyLTQ1,115200 rootfstype=squashfs,jffs2
|
||||
xway_cmdline=-console=ttyLTQ1,115200 rootfstype=squashfs,jffs2
|
||||
falcon_cmdline=-console=ttyLTQ0,115200 rootfstype=squashfs,jffs2
|
||||
|
||||
define CompressLzma
|
||||
$(STAGING_DIR_HOST)/bin/lzma e $(1) $(2)
|
||||
|
@ -184,6 +185,27 @@ define Image/Build/Profile/Generic
|
|||
endef
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_TARGET_lantiq_ase),y)
|
||||
define Image/BuildKernel/Profile/EASY50601
|
||||
$(call Image/BuildKernel/Template,EASY50601,$(ase_cmdline))
|
||||
endef
|
||||
|
||||
define Image/Build/Profile/EASY50601
|
||||
$(call Image/Build/$(1),$(1),EASY50601)
|
||||
endef
|
||||
|
||||
define Image/BuildKernel/Profile/Generic
|
||||
$(call Image/BuildKernel/Template,EASY50601,$(ase_cmdline))
|
||||
$(call Image/BuildKernel/Template,NONE)
|
||||
endef
|
||||
|
||||
define Image/Build/Profile/Generic
|
||||
$(call Image/Build/$(1),$(1),EASY50601)
|
||||
$(call Image/Build/$(1),$(1),NONE)
|
||||
$(CP) $(KDIR)/root.$(1) $(BIN_DIR)/$(IMG_PREFIX)-$(1).rootfs
|
||||
endef
|
||||
endif
|
||||
|
||||
define Image/BuildKernel
|
||||
$(call Image/BuildKernel/Profile/$(PROFILE))
|
||||
endef
|
||||
|
|
|
@ -0,0 +1,898 @@
|
|||
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
|
||||
@@ -174,6 +174,23 @@
|
||||
Members include the Acer PICA, MIPS Magnum 4000, MIPS Millennium and
|
||||
Olivetti M700-10 workstations.
|
||||
|
||||
+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(unsigned int irq);
|
||||
+extern void ltq_mask_and_ack_irq(unsigned int irq);
|
||||
+extern void ltq_enable_irq(unsigned int irq);
|
||||
+
|
||||
+/* 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, <q_cgu_resource) < 0)
|
||||
+ panic("Failed to insert cgu memory\n");
|
||||
+
|
||||
+ if (request_mem_region(ltq_cgu_resource.start,
|
||||
+ resource_size(<q_cgu_resource), "cgu") < 0)
|
||||
+ panic("Failed to request cgu memory\n");
|
||||
+
|
||||
+ ltq_cgu_membase = ioremap_nocache(ltq_cgu_resource.start,
|
||||
+ resource_size(<q_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,353 @@
|
||||
+/*
|
||||
+ * 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(unsigned int irq_nr)
|
||||
+{
|
||||
+ u32 ier = LTQ_ICU_IM0_IER;
|
||||
+
|
||||
+ irq_nr -= 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(unsigned int irq_nr)
|
||||
+{
|
||||
+ u32 ier = LTQ_ICU_IM0_IER;
|
||||
+ u32 isr = LTQ_ICU_IM0_ISR;
|
||||
+
|
||||
+ irq_nr -= 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(unsigned int irq_nr)
|
||||
+{
|
||||
+ u32 isr = LTQ_ICU_IM0_ISR;
|
||||
+
|
||||
+ irq_nr -= 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(unsigned int irq_nr)
|
||||
+{
|
||||
+ u32 ier = LTQ_ICU_IM0_IER;
|
||||
+
|
||||
+ irq_nr -= 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(unsigned int irq)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ ltq_enable_irq(irq);
|
||||
+ for (i = 0; i < MAX_EIU; i++) {
|
||||
+ if (irq == 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(unsigned int irq)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ ltq_disable_irq(irq);
|
||||
+ for (i = 0; i < MAX_EIU; i++) {
|
||||
+ if (irq == ltq_eiu_irq[i]) {
|
||||
+ /* disable */
|
||||
+ ltq_eiu_w32(ltq_eiu_r32(LTQ_EIU_EXIN_INEN) & ~(1 << i),
|
||||
+ LTQ_EIU_EXIN_INEN);
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+static void
|
||||
+ltq_end_irq(unsigned int irq)
|
||||
+{
|
||||
+ if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
|
||||
+ ltq_enable_irq(irq);
|
||||
+}
|
||||
+
|
||||
+static struct irq_chip
|
||||
+ltq_irq_type = {
|
||||
+ "ltq_irq",
|
||||
+ .enable = ltq_enable_irq,
|
||||
+ .disable = ltq_disable_irq,
|
||||
+ .unmask = ltq_enable_irq,
|
||||
+ .ack = ltq_ack_irq,
|
||||
+ .mask = ltq_disable_irq,
|
||||
+ .mask_ack = ltq_mask_and_ack_irq,
|
||||
+ .end = ltq_end_irq,
|
||||
+};
|
||||
+
|
||||
+#ifdef CONFIG_SOC_TYPE_XWAY
|
||||
+static struct irq_chip
|
||||
+ltq_eiu_type = {
|
||||
+ "ltq_eiu_irq",
|
||||
+ .startup = ltq_startup_eiu_irq,
|
||||
+ .shutdown = ltq_shutdown_eiu_irq,
|
||||
+ .enable = ltq_enable_irq,
|
||||
+ .disable = ltq_disable_irq,
|
||||
+ .unmask = ltq_enable_irq,
|
||||
+ .ack = ltq_ack_irq,
|
||||
+ .mask = ltq_disable_irq,
|
||||
+ .mask_ack = ltq_mask_and_ack_irq,
|
||||
+ .end = ltq_end_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, <q_icu_resource) < 0)
|
||||
+ panic("Failed to insert icu memory\n");
|
||||
+
|
||||
+ if (request_mem_region(ltq_icu_resource.start,
|
||||
+ resource_size(<q_icu_resource), "icu") < 0)
|
||||
+ panic("Failed to request icu memory\n");
|
||||
+
|
||||
+ ltq_icu_membase = ioremap_nocache(ltq_icu_resource.start,
|
||||
+ resource_size(<q_icu_resource));
|
||||
+ if (!ltq_icu_membase)
|
||||
+ panic("Failed to remap icu memory\n");
|
||||
+
|
||||
+#ifdef CONFIG_SOC_TYPE_XWAY
|
||||
+ if (insert_resource(&iomem_resource, <q_eiu_resource) < 0)
|
||||
+ panic("Failed to insert eiu memory\n");
|
||||
+
|
||||
+ if (request_mem_region(ltq_eiu_resource.start,
|
||||
+ resource_size(<q_eiu_resource), "eiu") < 0)
|
||||
+ panic("Failed to request eiu memory\n");
|
||||
+
|
||||
+ ltq_eiu_membase = ioremap_nocache(ltq_eiu_resource.start,
|
||||
+ resource_size(<q_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))
|
||||
+ set_irq_chip_and_handler(i, <q_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()))
|
||||
+ set_irq_chip_and_handler(i, <q_eiu_type, handle_level_irq);
|
||||
+ else
|
||||
+#endif
|
||||
+ set_irq_chip_and_handler(i, <q_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
|
||||
+ cp0_compare_irq = CP0_LEGACY_COMPARE_IRQ;
|
||||
+}
|
||||
+
|
||||
+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);
|
||||
+}
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,546 @@
|
|||
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
|
||||
|
||||
diff --git a/arch/mips/include/asm/mach-lantiq/lantiq_platform.h b/arch/mips/include/asm/mach-lantiq/lantiq_platform.h
|
||||
new file mode 100644
|
||||
index 0000000..1f1dba6
|
||||
--- /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
|
||||
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
|
||||
index f0d5329..4df8799 100644
|
||||
--- a/arch/mips/pci/Makefile
|
||||
+++ b/arch/mips/pci/Makefile
|
||||
@@ -41,6 +41,7 @@ obj-$(CONFIG_SIBYTE_SB1250) += fixup-sb1250.o pci-sb1250.o
|
||||
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
|
||||
diff --git a/arch/mips/pci/ops-lantiq.c b/arch/mips/pci/ops-lantiq.c
|
||||
new file mode 100644
|
||||
index 0000000..1f2afb5
|
||||
--- /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;
|
||||
+}
|
||||
diff --git a/arch/mips/pci/pci-lantiq.c b/arch/mips/pci/pci-lantiq.c
|
||||
new file mode 100644
|
||||
index 0000000..603d749
|
||||
--- /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 = <q_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(<q_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(<q_pci_driver);
|
||||
+ if (ret)
|
||||
+ printk(KERN_INFO "ltq_pci: Error registering platfom driver!");
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+arch_initcall(pcibios_init);
|
||||
diff --git a/arch/mips/pci/pci-lantiq.h b/arch/mips/pci/pci-lantiq.h
|
||||
new file mode 100644
|
||||
index 0000000..66bf6cd
|
||||
--- /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
|
||||
--
|
||||
1.7.2.3
|
||||
|
|
@ -0,0 +1,301 @@
|
|||
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
|
||||
@@ -259,6 +259,13 @@
|
||||
help
|
||||
Flash memory access on AMD Alchemy Pb/Db/RDK Reference 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_CONCAT && MTD_PARTITIONS && MTD_CFI_INTELEXT && BROKEN
|
||||
--- a/drivers/mtd/maps/Makefile
|
||||
+++ b/drivers/mtd/maps/Makefile
|
||||
@@ -61,3 +61,4 @@
|
||||
obj-$(CONFIG_MTD_RBTX4939) += rbtx4939-flash.o
|
||||
obj-$(CONFIG_MTD_VMU) += vmu-flash.o
|
||||
obj-$(CONFIG_MTD_GPIO_ADDR) += gpio-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(<q_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(<q_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");
|
|
@ -0,0 +1,338 @@
|
|||
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
|
||||
|
||||
diff --git a/arch/mips/lantiq/Makefile b/arch/mips/lantiq/Makefile
|
||||
index a268391..e5dae0e 100644
|
||||
--- 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
|
||||
|
||||
diff --git a/arch/mips/lantiq/devices.c b/arch/mips/lantiq/devices.c
|
||||
new file mode 100644
|
||||
index 0000000..7b82c34
|
||||
--- /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 = <q_nor_resource,
|
||||
+ .num_resources = 1,
|
||||
+};
|
||||
+
|
||||
+void __init ltq_register_nor(struct physmap_flash_data *data)
|
||||
+{
|
||||
+ ltq_nor.dev.platform_data = data;
|
||||
+ platform_device_register(<q_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, <q_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(<q_pci);
|
||||
+}
|
||||
+#else
|
||||
+void __init ltq_register_pci(struct ltq_pci_data *data)
|
||||
+{
|
||||
+ pr_err("kernel is compiled without PCI support\n");
|
||||
+}
|
||||
+#endif
|
||||
diff --git a/arch/mips/lantiq/devices.h b/arch/mips/lantiq/devices.h
|
||||
new file mode 100644
|
||||
index 0000000..2947bb1
|
||||
--- /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
|
||||
diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
|
||||
index 9c85ff9..74ce438 100644
|
||||
--- 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
|
||||
diff --git a/arch/mips/lantiq/xway/devices.c b/arch/mips/lantiq/xway/devices.c
|
||||
new file mode 100644
|
||||
index 0000000..a71b3b5
|
||||
--- /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,
|
||||
+ <q_gpio_resource[0], 1);
|
||||
+ platform_device_register_simple("ltq_gpio", 1,
|
||||
+ <q_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,
|
||||
+ <q_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, <q_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));
|
||||
+}
|
||||
diff --git a/arch/mips/lantiq/xway/devices.h b/arch/mips/lantiq/xway/devices.h
|
||||
new file mode 100644
|
||||
index 0000000..51f56b5
|
||||
--- /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
|
||||
--
|
||||
1.7.2.3
|
||||
|
|
@ -0,0 +1,170 @@
|
|||
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
|
||||
@@ -190,6 +190,7 @@
|
||||
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 @@
|
||||
};
|
||||
|
||||
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 @@
|
||||
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();
|
||||
+}
|
|
@ -0,0 +1,230 @@
|
|||
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
|
||||
|
||||
diff --git a/arch/mips/lantiq/Kconfig b/arch/mips/lantiq/Kconfig
|
||||
index 2780461..3fccf21 100644
|
||||
--- 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
|
||||
diff --git a/arch/mips/lantiq/machtypes.h b/arch/mips/lantiq/machtypes.h
|
||||
index ffcacfc..7e01b8c 100644
|
||||
--- 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
|
||||
diff --git a/arch/mips/lantiq/xway/Kconfig b/arch/mips/lantiq/xway/Kconfig
|
||||
new file mode 100644
|
||||
index 0000000..2b857de
|
||||
--- /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
|
||||
diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
|
||||
index 8c06a97..b1d3640 100644
|
||||
--- 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 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
|
||||
+
|
||||
+obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o
|
||||
+obj-$(CONFIG_LANTIQ_MACH_EASY50601) += mach-easy50601.o
|
||||
diff --git a/arch/mips/lantiq/xway/mach-easy50601.c b/arch/mips/lantiq/xway/mach-easy50601.c
|
||||
new file mode 100644
|
||||
index 0000000..d5aaf63
|
||||
--- /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);
|
||||
diff --git a/arch/mips/lantiq/xway/mach-easy50712.c b/arch/mips/lantiq/xway/mach-easy50712.c
|
||||
new file mode 100644
|
||||
index 0000000..e5e7e09
|
||||
--- /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(<q_pci_data);
|
||||
+}
|
||||
+
|
||||
+MIPS_MACHINE(LTQ_MACH_EASY50712,
|
||||
+ "EASY50712",
|
||||
+ "EASY50712 Eval Board",
|
||||
+ easy50712_init);
|
||||
--
|
||||
1.7.2.3
|
||||
|
|
@ -0,0 +1,330 @@
|
|||
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
|
||||
|
||||
diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
|
||||
index b1d3640..6b5e07e 100644
|
||||
--- 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
|
||||
diff --git a/arch/mips/lantiq/xway/gpio_ebu.c b/arch/mips/lantiq/xway/gpio_ebu.c
|
||||
new file mode 100644
|
||||
index 0000000..a479355
|
||||
--- /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(<q_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(<q_ebu_driver);
|
||||
+
|
||||
+ if (ret)
|
||||
+ pr_info("ltq_ebu : Error registering platfom driver!");
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+postcore_initcall(ltq_ebu_init);
|
||||
diff --git a/arch/mips/lantiq/xway/gpio_stp.c b/arch/mips/lantiq/xway/gpio_stp.c
|
||||
new file mode 100644
|
||||
index 0000000..67d59d6
|
||||
--- /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(<q_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(<q_stp_driver);
|
||||
+
|
||||
+ if (ret)
|
||||
+ pr_info("ltq_stp: error registering platfom driver");
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+postcore_initcall(ltq_stp_init);
|
||||
--
|
||||
1.7.2.3
|
||||
|
|
@ -1,30 +1,27 @@
|
|||
--- a/drivers/serial/Kconfig
|
||||
+++ b/drivers/serial/Kconfig
|
||||
@@ -1454,6 +1454,14 @@
|
||||
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
|
||||
+ Driver for the Lantiq SoC ASC hardware
|
||||
+
|
||||
config SERIAL_QE
|
||||
tristate "Freescale QUICC Engine serial port support"
|
||||
depends on QUICC_ENGINE
|
||||
--- a/drivers/serial/Makefile
|
||||
+++ b/drivers/serial/Makefile
|
||||
@@ -89,3 +89,4 @@
|
||||
obj-$(CONFIG_SERIAL_MRST_MAX3110) += mrst_max3110.o
|
||||
obj-$(CONFIG_SERIAL_MFD_HSU) += mfd.o
|
||||
obj-$(CONFIG_SERIAL_OMAP) += omap-serial.o
|
||||
+obj-$(CONFIG_SERIAL_LANTIQ) += lantiq.o
|
||||
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/serial/lantiq.c
|
||||
@@ -0,0 +1,772 @@
|
||||
@@ -0,0 +1,756 @@
|
||||
+/*
|
||||
+ * Based on drivers/char/serial.c, by Linus Torvalds, Theodore Ts'o.
|
||||
+ *
|
||||
|
@ -44,7 +41,7 @@
|
|||
+ * 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, Lantiq Deutschland
|
||||
+ * Copyright (C) 2010 Thomas Langer, <thomas.langer@lantiq.com>
|
||||
+ */
|
||||
+
|
||||
+#include <linux/slab.h>
|
||||
|
@ -62,112 +59,95 @@
|
|||
+#include <linux/io.h>
|
||||
+#include <linux/clk.h>
|
||||
+
|
||||
+#define lq_r32(reg) __raw_readl(reg)
|
||||
+#define lq_r8(reg) __raw_readb(reg)
|
||||
+#define lq_w32(val, reg) __raw_writel(val, reg)
|
||||
+#define lq_w8(val, reg) __raw_writeb(val, reg)
|
||||
+#define lq_w32_mask(clear, set, reg) lq_w32((lq_r32(reg) & ~(clear)) | (set), reg)
|
||||
+#include <lantiq_soc.h>
|
||||
+
|
||||
+#define PORT_IFXMIPSASC 111
|
||||
+#define PORT_LTQ_ASC 111
|
||||
+#define MAXPORTS 2
|
||||
+
|
||||
+#define UART_DUMMY_UER_RX 1
|
||||
+
|
||||
+#define DRVNAME "lq_asc"
|
||||
+
|
||||
+#define UART_DUMMY_UER_RX 1
|
||||
+#define DRVNAME "ltq_asc"
|
||||
+#ifdef __BIG_ENDIAN
|
||||
+#define IFXMIPS_ASC_TBUF (0x0020 + 3)
|
||||
+#define IFXMIPS_ASC_RBUF (0x0024 + 3)
|
||||
+#define LTQ_ASC_TBUF (0x0020 + 3)
|
||||
+#define LTQ_ASC_RBUF (0x0024 + 3)
|
||||
+#else
|
||||
+#define IFXMIPS_ASC_TBUF 0x0020
|
||||
+#define IFXMIPS_ASC_RBUF 0x0024
|
||||
+#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 IFXMIPS_ASC_FSTAT 0x0048
|
||||
+#define IFXMIPS_ASC_WHBSTATE 0x0018
|
||||
+#define IFXMIPS_ASC_STATE 0x0014
|
||||
+#define IFXMIPS_ASC_IRNCR 0x00F8
|
||||
+#define IFXMIPS_ASC_CLC 0x0000
|
||||
+#define IFXMIPS_ASC_ID 0x0008
|
||||
+#define IFXMIPS_ASC_PISEL 0x0004
|
||||
+#define IFXMIPS_ASC_TXFCON 0x0044
|
||||
+#define IFXMIPS_ASC_RXFCON 0x0040
|
||||
+#define IFXMIPS_ASC_CON 0x0010
|
||||
+#define IFXMIPS_ASC_BG 0x0050
|
||||
+#define IFXMIPS_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 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 ASCOPT_CS7 0x1
|
||||
+#define ASCOPT_CS8 0x2
|
||||
+#define ASCOPT_PARENB 0x4
|
||||
+#define ASCOPT_STOPB 0x8
|
||||
+#define ASCOPT_PARODD 0x0
|
||||
+#define ASCOPT_CREAD 0x20
|
||||
+#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_TXFFLOFF 8
|
||||
+#define ASCFSTAT_RXFREEMASK 0x003F0000
|
||||
+#define ASCFSTAT_RXFREEOFF 16
|
||||
+#define ASCFSTAT_TXFREEMASK 0x3F000000
|
||||
+#define ASCFSTAT_TXFREEOFF 24
|
||||
+#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);
|
||||
+extern void prom_printf(const char *fmt, ...);
|
||||
+static struct lq_uart_port *lqasc_port[2];
|
||||
+static struct ltq_uart_port *lqasc_port[MAXPORTS];
|
||||
+static struct uart_driver lqasc_reg;
|
||||
+static DEFINE_SPINLOCK(ltq_asc_lock);
|
||||
+
|
||||
+struct lq_uart_port {
|
||||
+struct ltq_uart_port {
|
||||
+ struct uart_port port;
|
||||
+ struct clk *clk;
|
||||
+ struct clk *clk;
|
||||
+ unsigned int tx_irq;
|
||||
+ unsigned int rx_irq;
|
||||
+ unsigned int err_irq;
|
||||
+};
|
||||
+
|
||||
+static inline struct
|
||||
+lq_uart_port *to_lq_uart_port(struct uart_port *port)
|
||||
+ltq_uart_port *to_ltq_uart_port(struct uart_port *port)
|
||||
+{
|
||||
+ return container_of(port, struct lq_uart_port, port);
|
||||
+ return container_of(port, struct ltq_uart_port, port);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
|
@ -180,16 +160,16 @@
|
|||
+lqasc_start_tx(struct uart_port *port)
|
||||
+{
|
||||
+ unsigned long flags;
|
||||
+ local_irq_save(flags);
|
||||
+ spin_lock_irqsave(<q_asc_lock, flags);
|
||||
+ lqasc_tx_chars(port);
|
||||
+ local_irq_restore(flags);
|
||||
+ spin_unlock_irqrestore(<q_asc_lock, flags);
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+lqasc_stop_rx(struct uart_port *port)
|
||||
+{
|
||||
+ lq_w32(ASCWHBSTATE_CLRREN, port->membase + IFXMIPS_ASC_WHBSTATE);
|
||||
+ ltq_w32(ASCWHBSTATE_CLRREN, port->membase + LTQ_ASC_WHBSTATE);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
|
@ -197,17 +177,22 @@
|
|||
+{
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+static int
|
||||
+lqasc_rx_chars(struct uart_port *port)
|
||||
+{
|
||||
+ struct tty_struct *tty = port->state->port.tty;
|
||||
+ struct tty_struct *tty = tty_port_tty_get(&port->state->port);
|
||||
+ unsigned int ch = 0, rsr = 0, fifocnt;
|
||||
+
|
||||
+ fifocnt = lq_r32(port->membase + IFXMIPS_ASC_FSTAT) & ASCFSTAT_RXFFLMASK;
|
||||
+ 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 = lq_r8(port->membase + IFXMIPS_ASC_RBUF);
|
||||
+ rsr = (lq_r32(port->membase + IFXMIPS_ASC_STATE)
|
||||
+ 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++;
|
||||
|
@ -219,17 +204,17 @@
|
|||
+ if (rsr & ASCSTATE_ANY) {
|
||||
+ if (rsr & ASCSTATE_PE) {
|
||||
+ port->icount.parity++;
|
||||
+ lq_w32_mask(0, ASCWHBSTATE_CLRPE,
|
||||
+ port->membase + IFXMIPS_ASC_WHBSTATE);
|
||||
+ ltq_w32_mask(0, ASCWHBSTATE_CLRPE,
|
||||
+ port->membase + LTQ_ASC_WHBSTATE);
|
||||
+ } else if (rsr & ASCSTATE_FE) {
|
||||
+ port->icount.frame++;
|
||||
+ lq_w32_mask(0, ASCWHBSTATE_CLRFE,
|
||||
+ port->membase + IFXMIPS_ASC_WHBSTATE);
|
||||
+ ltq_w32_mask(0, ASCWHBSTATE_CLRFE,
|
||||
+ port->membase + LTQ_ASC_WHBSTATE);
|
||||
+ }
|
||||
+ if (rsr & ASCSTATE_ROE) {
|
||||
+ port->icount.overrun++;
|
||||
+ lq_w32_mask(0, ASCWHBSTATE_CLRROE,
|
||||
+ port->membase + IFXMIPS_ASC_WHBSTATE);
|
||||
+ ltq_w32_mask(0, ASCWHBSTATE_CLRROE,
|
||||
+ port->membase + LTQ_ASC_WHBSTATE);
|
||||
+ }
|
||||
+
|
||||
+ rsr &= port->read_status_mask;
|
||||
|
@ -253,7 +238,8 @@
|
|||
+ }
|
||||
+ if (ch != 0)
|
||||
+ tty_flip_buffer_push(tty);
|
||||
+ return;
|
||||
+ tty_kref_put(tty);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
|
@ -265,10 +251,10 @@
|
|||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ while (((lq_r32(port->membase + IFXMIPS_ASC_FSTAT) &
|
||||
+ while (((ltq_r32(port->membase + LTQ_ASC_FSTAT) &
|
||||
+ ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF) != 0) {
|
||||
+ if (port->x_char) {
|
||||
+ lq_w8(port->x_char, port->membase + IFXMIPS_ASC_TBUF);
|
||||
+ ltq_w8(port->x_char, port->membase + LTQ_ASC_TBUF);
|
||||
+ port->icount.tx++;
|
||||
+ port->x_char = 0;
|
||||
+ continue;
|
||||
|
@ -277,8 +263,8 @@
|
|||
+ if (uart_circ_empty(xmit))
|
||||
+ break;
|
||||
+
|
||||
+ lq_w8(port->state->xmit.buf[port->state->xmit.tail],
|
||||
+ port->membase + IFXMIPS_ASC_TBUF);
|
||||
+ 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++;
|
||||
+ }
|
||||
|
@ -290,8 +276,11 @@
|
|||
+static irqreturn_t
|
||||
+lqasc_tx_int(int irq, void *_port)
|
||||
+{
|
||||
+ unsigned long flags;
|
||||
+ struct uart_port *port = (struct uart_port *)_port;
|
||||
+ lq_w32(ASC_IRNCR_TIR, port->membase + IFXMIPS_ASC_IRNCR);
|
||||
+ spin_lock_irqsave(<q_asc_lock, flags);
|
||||
+ ltq_w32(ASC_IRNCR_TIR, port->membase + LTQ_ASC_IRNCR);
|
||||
+ spin_unlock_irqrestore(<q_asc_lock, flags);
|
||||
+ lqasc_start_tx(port);
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
|
@ -299,19 +288,25 @@
|
|||
+static irqreturn_t
|
||||
+lqasc_err_int(int irq, void *_port)
|
||||
+{
|
||||
+ unsigned long flags;
|
||||
+ struct uart_port *port = (struct uart_port *)_port;
|
||||
+ spin_lock_irqsave(<q_asc_lock, flags);
|
||||
+ /* clear any pending interrupts */
|
||||
+ lq_w32_mask(0, ASCWHBSTATE_CLRPE | ASCWHBSTATE_CLRFE | ASCWHBSTATE_CLRROE,
|
||||
+ port->membase + IFXMIPS_ASC_WHBSTATE);
|
||||
+ ltq_w32_mask(0, ASCWHBSTATE_CLRPE | ASCWHBSTATE_CLRFE |
|
||||
+ ASCWHBSTATE_CLRROE, port->membase + LTQ_ASC_WHBSTATE);
|
||||
+ spin_unlock_irqrestore(<q_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;
|
||||
+ lq_w32(ASC_IRNCR_RIR, port->membase + IFXMIPS_ASC_IRNCR);
|
||||
+ spin_lock_irqsave(<q_asc_lock, flags);
|
||||
+ ltq_w32(ASC_IRNCR_RIR, port->membase + LTQ_ASC_IRNCR);
|
||||
+ lqasc_rx_chars(port);
|
||||
+ spin_unlock_irqrestore(<q_asc_lock, flags);
|
||||
+ return IRQ_HANDLED;
|
||||
+}
|
||||
+
|
||||
|
@ -319,7 +314,7 @@
|
|||
+lqasc_tx_empty(struct uart_port *port)
|
||||
+{
|
||||
+ int status;
|
||||
+ status = lq_r32(port->membase + IFXMIPS_ASC_FSTAT) & ASCFSTAT_TXFFLMASK;
|
||||
+ status = ltq_r32(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_TXFFLMASK;
|
||||
+ return status ? 0 : TIOCSER_TEMT;
|
||||
+}
|
||||
+
|
||||
|
@ -342,73 +337,75 @@
|
|||
+static int
|
||||
+lqasc_startup(struct uart_port *port)
|
||||
+{
|
||||
+ struct lq_uart_port *ifx_port = to_lq_uart_port(port);
|
||||
+ struct ltq_uart_port *ltq_port = to_ltq_uart_port(port);
|
||||
+ int retval;
|
||||
+
|
||||
+ port->uartclk = clk_get_rate(ifx_port->clk);
|
||||
+ port->uartclk = clk_get_rate(ltq_port->clk);
|
||||
+
|
||||
+ lq_w32_mask(ASCCLC_DISS | ASCCLC_RMCMASK, (1 << ASCCLC_RMCOFFSET),
|
||||
+ port->membase + IFXMIPS_ASC_CLC);
|
||||
+ ltq_w32_mask(ASCCLC_DISS | ASCCLC_RMCMASK, (1 << ASCCLC_RMCOFFSET),
|
||||
+ port->membase + LTQ_ASC_CLC);
|
||||
+
|
||||
+ lq_w32(0, port->membase + IFXMIPS_ASC_PISEL);
|
||||
+ lq_w32(
|
||||
+ ltq_w32(0, port->membase + LTQ_ASC_PISEL);
|
||||
+ ltq_w32(
|
||||
+ ((TXFIFO_FL << ASCTXFCON_TXFITLOFF) & ASCTXFCON_TXFITLMASK) |
|
||||
+ ASCTXFCON_TXFEN | ASCTXFCON_TXFFLU,
|
||||
+ port->membase + IFXMIPS_ASC_TXFCON);
|
||||
+ lq_w32(
|
||||
+ port->membase + LTQ_ASC_TXFCON);
|
||||
+ ltq_w32(
|
||||
+ ((RXFIFO_FL << ASCRXFCON_RXFITLOFF) & ASCRXFCON_RXFITLMASK)
|
||||
+ | ASCRXFCON_RXFEN | ASCRXFCON_RXFFLU,
|
||||
+ port->membase + IFXMIPS_ASC_RXFCON);
|
||||
+ /* make sure other settings are written to hardware before setting enable bits */
|
||||
+ port->membase + LTQ_ASC_RXFCON);
|
||||
+ /* make sure other settings are written to hardware before
|
||||
+ * setting enable bits
|
||||
+ */
|
||||
+ wmb();
|
||||
+ lq_w32_mask(0, ASCCON_M_8ASYNC | ASCCON_FEN | ASCCON_TOEN |
|
||||
+ ASCCON_ROEN, port->membase + IFXMIPS_ASC_CON);
|
||||
+ ltq_w32_mask(0, ASCCON_M_8ASYNC | ASCCON_FEN | ASCCON_TOEN |
|
||||
+ ASCCON_ROEN, port->membase + LTQ_ASC_CON);
|
||||
+
|
||||
+ retval = request_irq(ifx_port->tx_irq, lqasc_tx_int,
|
||||
+ 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(ifx_port->rx_irq, lqasc_rx_int,
|
||||
+ 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(ifx_port->err_irq, lqasc_err_int,
|
||||
+ 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;
|
||||
+ }
|
||||
+
|
||||
+ lq_w32(ASC_IRNREN_RX | ASC_IRNREN_ERR | ASC_IRNREN_TX,
|
||||
+ port->membase + IFXMIPS_ASC_IRNREN);
|
||||
+ ltq_w32(ASC_IRNREN_RX | ASC_IRNREN_ERR | ASC_IRNREN_TX,
|
||||
+ port->membase + LTQ_ASC_IRNREN);
|
||||
+ return 0;
|
||||
+
|
||||
+err2:
|
||||
+ free_irq(ifx_port->rx_irq, port);
|
||||
+ free_irq(ltq_port->rx_irq, port);
|
||||
+err1:
|
||||
+ free_irq(ifx_port->tx_irq, port);
|
||||
+ free_irq(ltq_port->tx_irq, port);
|
||||
+ return retval;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+lqasc_shutdown(struct uart_port *port)
|
||||
+{
|
||||
+ struct lq_uart_port *ifx_port = to_lq_uart_port(port);
|
||||
+ free_irq(ifx_port->tx_irq, port);
|
||||
+ free_irq(ifx_port->rx_irq, port);
|
||||
+ free_irq(ifx_port->err_irq, 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);
|
||||
+
|
||||
+ lq_w32(0, port->membase + IFXMIPS_ASC_CON);
|
||||
+ lq_w32_mask(ASCRXFCON_RXFEN, ASCRXFCON_RXFFLU,
|
||||
+ port->membase + IFXMIPS_ASC_RXFCON);
|
||||
+ lq_w32_mask(ASCTXFCON_TXFEN, ASCTXFCON_TXFFLU,
|
||||
+ port->membase + IFXMIPS_ASC_TXFCON);
|
||||
+ 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
|
||||
|
@ -417,7 +414,7 @@
|
|||
+{
|
||||
+ unsigned int cflag;
|
||||
+ unsigned int iflag;
|
||||
+ unsigned int quot;
|
||||
+ unsigned int divisor;
|
||||
+ unsigned int baud;
|
||||
+ unsigned int con = 0;
|
||||
+ unsigned long flags;
|
||||
|
@ -433,10 +430,14 @@
|
|||
+ 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;
|
||||
+
|
||||
|
@ -470,41 +471,45 @@
|
|||
+ /* set error signals - framing, parity and overrun, enable receiver */
|
||||
+ con |= ASCCON_FEN | ASCCON_TOEN | ASCCON_ROEN;
|
||||
+
|
||||
+ local_irq_save(flags);
|
||||
+ spin_lock_irqsave(<q_asc_lock, flags);
|
||||
+
|
||||
+ /* set up CON */
|
||||
+ lq_w32_mask(0, con, port->membase + IFXMIPS_ASC_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);
|
||||
+ quot = uart_get_divisor(port, baud);
|
||||
+ quot = quot / 2 - 1;
|
||||
+ divisor = uart_get_divisor(port, baud);
|
||||
+ divisor = divisor / 2 - 1;
|
||||
+
|
||||
+ /* disable the baudrate generator */
|
||||
+ lq_w32_mask(ASCCON_R, 0, port->membase + IFXMIPS_ASC_CON);
|
||||
+ ltq_w32_mask(ASCCON_R, 0, port->membase + LTQ_ASC_CON);
|
||||
+
|
||||
+ /* make sure the fractional divider is off */
|
||||
+ lq_w32_mask(ASCCON_FDE, 0, port->membase + IFXMIPS_ASC_CON);
|
||||
+ ltq_w32_mask(ASCCON_FDE, 0, port->membase + LTQ_ASC_CON);
|
||||
+
|
||||
+ /* set up to use divisor of 2 */
|
||||
+ lq_w32_mask(ASCCON_BRS, 0, port->membase + IFXMIPS_ASC_CON);
|
||||
+ ltq_w32_mask(ASCCON_BRS, 0, port->membase + LTQ_ASC_CON);
|
||||
+
|
||||
+ /* now we can write the new baudrate into the register */
|
||||
+ lq_w32(quot, port->membase + IFXMIPS_ASC_BG);
|
||||
+ ltq_w32(divisor, port->membase + LTQ_ASC_BG);
|
||||
+
|
||||
+ /* turn the baudrate generator back on */
|
||||
+ lq_w32_mask(0, ASCCON_R, port->membase + IFXMIPS_ASC_CON);
|
||||
+ ltq_w32_mask(0, ASCCON_R, port->membase + LTQ_ASC_CON);
|
||||
+
|
||||
+ /* enable rx */
|
||||
+ lq_w32(ASCWHBSTATE_SETREN, port->membase + IFXMIPS_ASC_WHBSTATE);
|
||||
+ ltq_w32(ASCWHBSTATE_SETREN, port->membase + LTQ_ASC_WHBSTATE);
|
||||
+
|
||||
+ local_irq_restore(flags);
|
||||
+ spin_unlock_irqrestore(<q_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_IFXMIPSASC)
|
||||
+ if (port->type == PORT_LTQ_ASC)
|
||||
+ return DRVNAME;
|
||||
+ else
|
||||
+ return NULL;
|
||||
|
@ -523,16 +528,26 @@
|
|||
+lqasc_request_port(struct uart_port *port)
|
||||
+{
|
||||
+ struct platform_device *pdev = to_platform_device(port->dev);
|
||||
+ struct resource *mmres;
|
||||
+ struct resource *res;
|
||||
+ int size;
|
||||
+
|
||||
+ mmres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
+ if (!mmres)
|
||||
+ 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(mmres);
|
||||
+ }
|
||||
+ 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 = ioremap_nocache(port->mapbase, size);
|
||||
+ port->membase = devm_ioremap_nocache(&pdev->dev,
|
||||
+ port->mapbase, size);
|
||||
+ if (port->membase == NULL)
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
|
@ -543,7 +558,7 @@
|
|||
+lqasc_config_port(struct uart_port *port, int flags)
|
||||
+{
|
||||
+ if (flags & UART_CONFIG_TYPE) {
|
||||
+ port->type = PORT_IFXMIPSASC;
|
||||
+ port->type = PORT_LTQ_ASC;
|
||||
+ lqasc_request_port(port);
|
||||
+ }
|
||||
+}
|
||||
|
@ -553,7 +568,7 @@
|
|||
+ struct serial_struct *ser)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+ if (ser->type != PORT_UNKNOWN && ser->type != PORT_IFXMIPSASC)
|
||||
+ if (ser->type != PORT_UNKNOWN && ser->type != PORT_LTQ_ASC)
|
||||
+ ret = -EINVAL;
|
||||
+ if (ser->irq < 0 || ser->irq >= NR_IRQS)
|
||||
+ ret = -EINVAL;
|
||||
|
@ -590,38 +605,38 @@
|
|||
+ return;
|
||||
+
|
||||
+ do {
|
||||
+ fifofree = (lq_r32(port->membase + IFXMIPS_ASC_FSTAT)
|
||||
+ fifofree = (ltq_r32(port->membase + LTQ_ASC_FSTAT)
|
||||
+ & ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF;
|
||||
+ } while (fifofree == 0);
|
||||
+ lq_w8(ch, port->membase + IFXMIPS_ASC_TBUF);
|
||||
+ ltq_w8(ch, port->membase + LTQ_ASC_TBUF);
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static void
|
||||
+lqasc_console_write(struct console *co, const char *s, u_int count)
|
||||
+{
|
||||
+ struct lq_uart_port *ifx_port;
|
||||
+ struct ltq_uart_port *ltq_port;
|
||||
+ struct uart_port *port;
|
||||
+ unsigned long flags;
|
||||
+
|
||||
+ if (co->index >= MAXPORTS)
|
||||
+ return;
|
||||
+
|
||||
+ ifx_port = lqasc_port[co->index];
|
||||
+ if (!ifx_port)
|
||||
+ ltq_port = lqasc_port[co->index];
|
||||
+ if (!ltq_port)
|
||||
+ return;
|
||||
+
|
||||
+ port = &ifx_port->port;
|
||||
+ port = <q_port->port;
|
||||
+
|
||||
+ local_irq_save(flags);
|
||||
+ spin_lock_irqsave(<q_asc_lock, flags);
|
||||
+ uart_console_write(port, s, count, lqasc_console_putchar);
|
||||
+ local_irq_restore(flags);
|
||||
+ spin_unlock_irqrestore(<q_asc_lock, flags);
|
||||
+}
|
||||
+
|
||||
+static int __init
|
||||
+lqasc_console_setup(struct console *co, char *options)
|
||||
+{
|
||||
+ struct lq_uart_port *ifx_port;
|
||||
+ struct ltq_uart_port *ltq_port;
|
||||
+ struct uart_port *port;
|
||||
+ int baud = 115200;
|
||||
+ int bits = 8;
|
||||
|
@ -631,13 +646,13 @@
|
|||
+ if (co->index >= MAXPORTS)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ ifx_port = lqasc_port[co->index];
|
||||
+ if (!ifx_port)
|
||||
+ ltq_port = lqasc_port[co->index];
|
||||
+ if (!ltq_port)
|
||||
+ return -ENODEV;
|
||||
+
|
||||
+ port = &ifx_port->port;
|
||||
+ port = <q_port->port;
|
||||
+
|
||||
+ port->uartclk = clk_get_rate(ifx_port->clk);
|
||||
+ port->uartclk = clk_get_rate(ltq_port->clk);
|
||||
+
|
||||
+ if (options)
|
||||
+ uart_parse_options(options, &baud, &parity, &bits, &flow);
|
||||
|
@ -645,7 +660,7 @@
|
|||
+}
|
||||
+
|
||||
+static struct console lqasc_console = {
|
||||
+ .name = "ttyS",
|
||||
+ .name = "ttyLTQ",
|
||||
+ .write = lqasc_console_write,
|
||||
+ .device = uart_console_device,
|
||||
+ .setup = lqasc_console_setup,
|
||||
|
@ -665,17 +680,17 @@
|
|||
+static struct uart_driver lqasc_reg = {
|
||||
+ .owner = THIS_MODULE,
|
||||
+ .driver_name = DRVNAME,
|
||||
+ .dev_name = "ttyS",
|
||||
+ .major = TTY_MAJOR,
|
||||
+ .minor = 64,
|
||||
+ .dev_name = "ttyLTQ",
|
||||
+ .major = 0,
|
||||
+ .minor = 0,
|
||||
+ .nr = MAXPORTS,
|
||||
+ .cons = &lqasc_console,
|
||||
+};
|
||||
+
|
||||
+static int __devinit
|
||||
+static int __init
|
||||
+lqasc_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct lq_uart_port *ifx_port;
|
||||
+ struct ltq_uart_port *ltq_port;
|
||||
+ struct uart_port *port;
|
||||
+ struct resource *mmres, *irqres;
|
||||
+ int tx_irq, rx_irq, err_irq;
|
||||
|
@ -700,69 +715,43 @@
|
|||
+ }
|
||||
+
|
||||
+ tx_irq = platform_get_irq_byname(pdev, "tx");
|
||||
+ if (tx_irq < 0) {
|
||||
+ /* without named resources: assume standard irq scheme */
|
||||
+ tx_irq = irqres->start;
|
||||
+ rx_irq = irqres->start+2;
|
||||
+ err_irq = irqres->start+3;
|
||||
+ } else {
|
||||
+ /* other irqs must be named also! */
|
||||
+ rx_irq = platform_get_irq_byname(pdev, "rx");
|
||||
+ err_irq = platform_get_irq_byname(pdev, "err");
|
||||
+ if ((rx_irq < 0) | (err_irq < 0))
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+ 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;
|
||||
+
|
||||
+ ifx_port = kzalloc(sizeof(struct lq_uart_port), GFP_KERNEL);
|
||||
+ if (!ifx_port)
|
||||
+ ltq_port = kzalloc(sizeof(struct ltq_uart_port), GFP_KERNEL);
|
||||
+ if (!ltq_port)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ port = &ifx_port->port;
|
||||
+ port = <q_port->port;
|
||||
+
|
||||
+ port->iotype = SERIAL_IO_MEM;
|
||||
+ port->flags = ASYNC_BOOT_AUTOCONF | UPF_IOREMAP;
|
||||
+ port->ops = &lqasc_pops;
|
||||
+ port->fifosize = 16;
|
||||
+ port->type = PORT_IFXMIPSASC,
|
||||
+ 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;
|
||||
+
|
||||
+ ifx_port->clk = clk;
|
||||
+ ltq_port->clk = clk;
|
||||
+
|
||||
+ ifx_port->tx_irq = tx_irq;
|
||||
+ ifx_port->rx_irq = rx_irq;
|
||||
+ ifx_port->err_irq = err_irq;
|
||||
+ ltq_port->tx_irq = tx_irq;
|
||||
+ ltq_port->rx_irq = rx_irq;
|
||||
+ ltq_port->err_irq = err_irq;
|
||||
+
|
||||
+ lqasc_port[pdev->id] = ifx_port;
|
||||
+ platform_set_drvdata(pdev, ifx_port);
|
||||
+ lqasc_port[pdev->id] = ltq_port;
|
||||
+ platform_set_drvdata(pdev, ltq_port);
|
||||
+
|
||||
+ ret = uart_add_one_port(&lqasc_reg, port);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int __devexit
|
||||
+lqasc_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ struct lq_uart_port *ifx_port = platform_get_drvdata(pdev);
|
||||
+ int ret;
|
||||
+
|
||||
+ clk_put(ifx_port->clk);
|
||||
+ platform_set_drvdata(pdev, NULL);
|
||||
+ lqasc_port[pdev->id] = NULL;
|
||||
+ ret = uart_remove_one_port(&lqasc_reg, &ifx_port->port);
|
||||
+ kfree(ifx_port);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct platform_driver lqasc_driver = {
|
||||
+ .probe = lqasc_probe,
|
||||
+ .remove = __devexit_p(lqasc_remove),
|
||||
+
|
||||
+ .driver = {
|
||||
+ .name = DRVNAME,
|
||||
+ .owner = THIS_MODULE,
|
||||
|
@ -778,22 +767,38 @@
|
|||
+ if (ret != 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = platform_driver_register(&lqasc_driver);
|
||||
+ ret = platform_driver_probe(&lqasc_driver, lqasc_probe);
|
||||
+ if (ret != 0)
|
||||
+ uart_unregister_driver(&lqasc_reg);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+void __exit
|
||||
+exit_lqasc(void)
|
||||
+{
|
||||
+ platform_driver_unregister(&lqasc_driver);
|
||||
+ uart_unregister_driver(&lqasc_reg);
|
||||
+}
|
||||
+
|
||||
+module_init(init_lqasc);
|
||||
+module_exit(exit_lqasc);
|
||||
+
|
||||
+MODULE_DESCRIPTION("Lantiq serial port driver");
|
||||
+MODULE_LICENSE("GPL");
|
||||
--- a/drivers/serial/Kconfig
|
||||
+++ b/drivers/serial/Kconfig
|
||||
@@ -1383,6 +1383,14 @@
|
||||
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/serial/Makefile
|
||||
+++ b/drivers/serial/Makefile
|
||||
@@ -81,3 +81,4 @@
|
||||
obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o
|
||||
obj-$(CONFIG_SERIAL_QE) += ucc_uart.o
|
||||
obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o
|
||||
+obj-$(CONFIG_SERIAL_LANTIQ) += lantiq.o
|
|
@ -0,0 +1,387 @@
|
|||
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
|
||||
|
||||
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 343e82c..4827afb 100644
|
||||
--- 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
|
||||
diff --git a/arch/mips/include/asm/mach-lantiq/xway/xway_dma.h b/arch/mips/include/asm/mach-lantiq/xway/xway_dma.h
|
||||
new file mode 100644
|
||||
index 0000000..872943a
|
||||
--- /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
|
||||
diff --git a/arch/mips/lantiq/xway/Makefile b/arch/mips/lantiq/xway/Makefile
|
||||
index 6b5e07e..c517f2e 100644
|
||||
--- 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
|
||||
diff --git a/arch/mips/lantiq/xway/devices.h b/arch/mips/lantiq/xway/devices.h
|
||||
index 51f56b5..d573084 100644
|
||||
--- 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);
|
||||
diff --git a/arch/mips/lantiq/xway/dma.c b/arch/mips/lantiq/xway/dma.c
|
||||
new file mode 100644
|
||||
index 0000000..4278a45
|
||||
--- /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, <q_dma_resource) < 0)
|
||||
+ panic("Failed to insert dma memory\n");
|
||||
+
|
||||
+ if (request_mem_region(ltq_dma_resource.start,
|
||||
+ resource_size(<q_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(<q_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);
|
||||
--
|
||||
1.7.2.3
|
||||
|
|
@ -0,0 +1,943 @@
|
|||
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 @@
|
||||
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 @@
|
||||
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 = <q_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(<q_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
|
||||
@@ -1951,6 +1951,13 @@
|
||||
This driver supports the ethernet MACs in the Broadcom 63xx
|
||||
MIPS chipset family (BCM63XX).
|
||||
|
||||
+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"
|
||||
|
||||
endif # NET_ETHERNET
|
||||
--- a/drivers/net/Makefile
|
||||
+++ b/drivers/net/Makefile
|
||||
@@ -246,6 +246,7 @@
|
||||
obj-$(CONFIG_MLX4_CORE) += mlx4/
|
||||
obj-$(CONFIG_ENC28J60) += enc28j60.o
|
||||
obj-$(CONFIG_ETHOC) += ethoc.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,814 @@
|
||||
+/*
|
||||
+ * 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), <q_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);
|
||||
+ struct mii_ioctl_data *data = if_mii(rq);
|
||||
+
|
||||
+ /* TODO: mii-toll reports "No MII transceiver present!." ?!*/
|
||||
+ return phy_mii_ioctl(priv->phydev, data, 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 = <q_eth_netdev_ops;
|
||||
+ dev->ethtool_ops = <q_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(<q_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(<q_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");
|
|
@ -0,0 +1,50 @@
|
|||
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(-)
|
||||
|
||||
diff --git a/arch/mips/lantiq/xway/mach-easy50712.c b/arch/mips/lantiq/xway/mach-easy50712.c
|
||||
index e5e7e09..ea5027b 100644
|
||||
--- 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(<q_pci_data);
|
||||
+ ltq_register_etop(<q_eth_data);
|
||||
}
|
||||
|
||||
MIPS_MACHINE(LTQ_MACH_EASY50712,
|
||||
--
|
||||
1.7.2.3
|
||||
|
|
@ -0,0 +1,310 @@
|
|||
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
|
||||
@@ -850,6 +850,12 @@
|
||||
help
|
||||
Hardware driver for the built-in watchdog timer on TXx9 MIPS SoCs.
|
||||
|
||||
+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
|
||||
@@ -113,6 +113,7 @@
|
||||
obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o
|
||||
obj-$(CONFIG_AR7_WDT) += ar7_wdt.o
|
||||
obj-$(CONFIG_TXX9_WDT) += txx9wdt.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, <q_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, <q_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 = <q_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(<q_wdt_miscdev);
|
||||
+}
|
||||
+
|
||||
+static int __devexit
|
||||
+ltq_wdt_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ misc_deregister(<q_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(<q_wdt_driver, ltq_wdt_probe);
|
||||
+}
|
||||
+
|
||||
+static void __exit
|
||||
+exit_ltq_wdt(void)
|
||||
+{
|
||||
+ return platform_driver_unregister(<q_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);
|
|
@ -12406,18 +12406,6 @@
|
|||
+extern int sys_gpe_hw_is_activated(u32 mask);
|
||||
+
|
||||
+#endif /* __FALCON_SYSCTRL_H */
|
||||
--- a/arch/mips/include/asm/mach-lantiq/lantiq_regs.h
|
||||
+++ b/arch/mips/include/asm/mach-lantiq/lantiq_regs.h
|
||||
@@ -12,6 +12,9 @@
|
||||
#ifdef CONFIG_SOC_LANTIQ_XWAY
|
||||
#include <xway.h>
|
||||
#include <xway_irq.h>
|
||||
+#elif defined(CONFIG_SOC_LANTIQ_FALCON)
|
||||
+#include <lantiq_falcon.h>
|
||||
+#include <lantiq_falcon_irq.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
--- /dev/null
|
||||
+++ b/arch/mips/include/asm/mach-lantiq/falcon/cpu-feature-overrides.h
|
||||
@@ -0,0 +1,58 @@
|
|
@ -1,7 +1,7 @@
|
|||
--- /dev/null
|
||||
+++ b/arch/mips/lantiq/falcon/Kconfig
|
||||
@@ -0,0 +1,11 @@
|
||||
+if SOC_LANTIQ_FALCON
|
||||
+if SOC_FALCON
|
||||
+
|
||||
+menu "Mips Machine"
|
||||
+
|
||||
|
@ -20,7 +20,7 @@
|
|||
+obj-$(CONFIG_LANTIQ_MACH_EASY98000) += mach-easy98000.o
|
||||
--- /dev/null
|
||||
+++ b/arch/mips/lantiq/falcon/clk-falcon.c
|
||||
@@ -0,0 +1,46 @@
|
||||
@@ -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 as published by
|
||||
|
@ -38,35 +38,37 @@
|
|||
+#include <asm/irq.h>
|
||||
+#include <asm/div64.h>
|
||||
+
|
||||
+#include <falcon.h>
|
||||
+#include <lantiq_soc.h>
|
||||
+
|
||||
+#include <falcon/sys1_reg.h>
|
||||
+#include <falcon.h>
|
||||
+#include <gpon_reg_base.h>
|
||||
+#include <sys1_reg.h>
|
||||
+
|
||||
+static struct gpon_reg_sys1 * const pSYS1 = (struct gpon_reg_sys1 *)GPON_SYS1_BASE;
|
||||
+
|
||||
+unsigned int
|
||||
+lq_get_io_region_clock(void)
|
||||
+ltq_get_io_region_clock(void)
|
||||
+{
|
||||
+ return 200000000; /* 200 MHz */
|
||||
+}
|
||||
+EXPORT_SYMBOL(lq_get_io_region_clock);
|
||||
+EXPORT_SYMBOL(ltq_get_io_region_clock);
|
||||
+
|
||||
+unsigned int
|
||||
+lq_get_cpu_hz(void)
|
||||
+ltq_get_cpu_hz(void)
|
||||
+{
|
||||
+ if ((lq_r32(&pSYS1->cpu0cc) & CPU0CC_CPUDIV) == CPU0CC_CPUDIV_SELFHALF)
|
||||
+ if ((ltq_r32(&pSYS1->cpu0cc) & CPU0CC_CPUDIV) == CPU0CC_CPUDIV_SELFHALF)
|
||||
+ return 200000000; /* 200 MHz */
|
||||
+ else
|
||||
+ return 400000000; /* 400 MHz */
|
||||
+}
|
||||
+EXPORT_SYMBOL(lq_get_cpu_hz);
|
||||
+EXPORT_SYMBOL(ltq_get_cpu_hz);
|
||||
+
|
||||
+unsigned int
|
||||
+lq_get_fpi_hz(void)
|
||||
+ltq_get_fpi_hz(void)
|
||||
+{
|
||||
+ return 100000000;
|
||||
+}
|
||||
+EXPORT_SYMBOL(lq_get_fpi_hz);
|
||||
+EXPORT_SYMBOL(ltq_get_fpi_hz);
|
||||
--- /dev/null
|
||||
+++ b/arch/mips/lantiq/falcon/devices.c
|
||||
@@ -0,0 +1,180 @@
|
||||
|
@ -101,15 +103,15 @@
|
|||
+
|
||||
+#include "devices.h"
|
||||
+
|
||||
+unsigned char lq_ethaddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
+EXPORT_SYMBOL(lq_ethaddr);
|
||||
+unsigned char ltq_ethaddr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
+EXPORT_SYMBOL(ltq_ethaddr);
|
||||
+
|
||||
+static int __init
|
||||
+falcon_set_ethaddr(char *str)
|
||||
+{
|
||||
+ sscanf(str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx",
|
||||
+ &lq_ethaddr[0], &lq_ethaddr[1], &lq_ethaddr[2],
|
||||
+ &lq_ethaddr[3], &lq_ethaddr[4], &lq_ethaddr[5]);
|
||||
+ <q_ethaddr[0], <q_ethaddr[1], <q_ethaddr[2],
|
||||
+ <q_ethaddr[3], <q_ethaddr[4], <q_ethaddr[5]);
|
||||
+ return 0;
|
||||
+}
|
||||
+__setup("ethaddr=", falcon_set_ethaddr);
|
||||
|
@ -135,11 +137,11 @@
|
|||
+{
|
||||
+ switch (port) {
|
||||
+ case 0:
|
||||
+ platform_device_register_simple("lq_asc", 0,
|
||||
+ platform_device_register_simple("ltq_asc", 0,
|
||||
+ falcon_asc0_resources, ARRAY_SIZE(falcon_asc0_resources));
|
||||
+ break;
|
||||
+ case 1:
|
||||
+ platform_device_register_simple("lq_asc", 1,
|
||||
+ platform_device_register_simple("ltq_asc", 1,
|
||||
+ falcon_asc1_resources, ARRAY_SIZE(falcon_asc1_resources));
|
||||
+ break;
|
||||
+ default:
|
||||
|
@ -148,37 +150,37 @@
|
|||
+}
|
||||
+
|
||||
+/* nor flash */
|
||||
+static struct resource lq_nor_resource =
|
||||
+ MEM_RES("nor",LQ_FLASH_START,LQ_FLASH_START + LQ_FLASH_MAX - 1);
|
||||
+static struct resource ltq_nor_resource =
|
||||
+ MEM_RES("nor",LTQ_FLASH_START,LTQ_FLASH_START + LTQ_FLASH_MAX - 1);
|
||||
+
|
||||
+static struct platform_device lq_nor = {
|
||||
+ .name = "lq_nor",
|
||||
+ .resource = &lq_nor_resource,
|
||||
+static struct platform_device ltq_nor = {
|
||||
+ .name = "ltq_nor",
|
||||
+ .resource = <q_nor_resource,
|
||||
+ .num_resources = 1,
|
||||
+};
|
||||
+
|
||||
+void __init falcon_register_nor(struct physmap_flash_data *data)
|
||||
+{
|
||||
+ lq_nor.dev.platform_data = data;
|
||||
+ platform_device_register(&lq_nor);
|
||||
+ ltq_nor.dev.platform_data = data;
|
||||
+ platform_device_register(<q_nor);
|
||||
+}
|
||||
+
|
||||
+/* spi flash */
|
||||
+static struct resource lq_spi_resources[] = {
|
||||
+static struct resource ltq_spi_resources[] = {
|
||||
+ MEM_RES("ebu", GPON_EBU_BASE, GPON_EBU_END),
|
||||
+ MEM_RES("sys1", GPON_SYS1_BASE, GPON_SYS1_END)
|
||||
+};
|
||||
+
|
||||
+static struct platform_device lq_spi = {
|
||||
+static struct platform_device ltq_spi = {
|
||||
+ .name = "falcon_spi",
|
||||
+ .resource = lq_spi_resources,
|
||||
+ .num_resources = ARRAY_SIZE(lq_spi_resources)
|
||||
+ .resource = ltq_spi_resources,
|
||||
+ .num_resources = ARRAY_SIZE(ltq_spi_resources)
|
||||
+};
|
||||
+
|
||||
+void __init falcon_register_spi_flash(struct spi_board_info *data)
|
||||
+{
|
||||
+ spi_register_board_info(data, 1);
|
||||
+ platform_device_register(&lq_spi);
|
||||
+ platform_device_register(<q_spi);
|
||||
+}
|
||||
+
|
||||
+/* watchdog */
|
||||
|
@ -187,7 +189,7 @@
|
|||
+
|
||||
+void __init falcon_register_wdt(void)
|
||||
+{
|
||||
+ platform_device_register_simple("lq_wdt", 0, &falcon_wdt_resource, 1);
|
||||
+ platform_device_register_simple("ltq_wdt", 0, &falcon_wdt_resource, 1);
|
||||
+}
|
||||
+
|
||||
+/* gpio */
|
||||
|
@ -248,7 +250,7 @@
|
|||
+
|
||||
+void __init falcon_register_crypto(void)
|
||||
+{
|
||||
+ platform_device_register_simple("lq_falcon_deu", 0, NULL, 0);
|
||||
+ platform_device_register_simple("ltq_falcon_deu", 0, NULL, 0);
|
||||
+}
|
||||
--- /dev/null
|
||||
+++ b/arch/mips/lantiq/falcon/devices.h
|
||||
|
@ -276,7 +278,7 @@
|
|||
+#endif
|
||||
--- /dev/null
|
||||
+++ b/arch/mips/lantiq/falcon/prom.c
|
||||
@@ -0,0 +1,44 @@
|
||||
@@ -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 as published by
|
||||
|
@ -291,6 +293,8 @@
|
|||
+#include <asm/bootinfo.h>
|
||||
+#include <asm/time.h>
|
||||
+
|
||||
+#include <lantiq_soc.h>
|
||||
+
|
||||
+#include <falcon.h>
|
||||
+
|
||||
+#include <falcon/gpon_reg_base.h>
|
||||
|
@ -304,10 +308,16 @@
|
|||
+#define SOC_FALCON "Falcon"
|
||||
+
|
||||
+void __init
|
||||
+lq_soc_detect(struct lq_soc_info *i)
|
||||
+ltq_soc_setup(void)
|
||||
+{
|
||||
+ i->partnum = (lq_r32(&pSTATUS->chipid) & STATUS_CHIPID_PARTNR_MASK) >> STATUS_CHIPID_PARTNR_OFFSET;
|
||||
+ i->rev = (lq_r32(&pSTATUS->chipid) & STATUS_CHIPID_VERSION_MASK) >> STATUS_CHIPID_VERSION_OFFSET;
|
||||
+ /* not used */
|
||||
+}
|
||||
+
|
||||
+void __init
|
||||
+ltq_soc_detect(struct ltq_soc_info *i)
|
||||
+{
|
||||
+ i->partnum = (ltq_r32(&pSTATUS->chipid) & STATUS_CHIPID_PARTNR_MASK) >> STATUS_CHIPID_PARTNR_OFFSET;
|
||||
+ i->rev = (ltq_r32(&pSTATUS->chipid) & STATUS_CHIPID_VERSION_MASK) >> STATUS_CHIPID_VERSION_OFFSET;
|
||||
+ switch (i->partnum)
|
||||
+ {
|
||||
+ case SOC_ID_FALCON:
|
||||
|
@ -1173,7 +1183,7 @@
|
|||
+module_exit(falcon_gpio_exit);
|
||||
--- /dev/null
|
||||
+++ b/arch/mips/include/asm/mach-lantiq/falcon/falcon.h
|
||||
@@ -0,0 +1,30 @@
|
||||
@@ -0,0 +1,16 @@
|
||||
+/*
|
||||
+ * 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
|
||||
|
@ -1184,29 +1194,15 @@
|
|||
+ * Copyright (C) 2010 John Crispin <blogic@openwrt.org>
|
||||
+ */
|
||||
+
|
||||
+#ifdef CONFIG_SOC_LANTIQ_FALCON
|
||||
+#ifdef CONFIG_SOC_FALCON
|
||||
+
|
||||
+#ifndef _LQ_FALCON_H__
|
||||
+#define _LQ_FALCON_H__
|
||||
+
|
||||
+#include <lantiq.h>
|
||||
+#include <lantiq_soc.h>
|
||||
+#include <falcon/gpon_reg_base.h>
|
||||
+
|
||||
+/*------------ GENERAL */
|
||||
+#define BOARD_SYSTEM_TYPE "LANTIQ"
|
||||
+
|
||||
+/*------------ Chip IDs */
|
||||
+#define SOC_ID_FALCON 0x01B8
|
||||
+
|
||||
+/*------------ SoC Types */
|
||||
+#define SOC_TYPE_FALCON 0x01
|
||||
+
|
||||
+#endif
|
||||
+
|
||||
+#endif
|
||||
--- /dev/null
|
||||
+++ b/arch/mips/lantiq/falcon/reset.c
|
||||
@@ -0,0 +1,72 @@
|
||||
@@ -0,0 +1,80 @@
|
||||
+/*
|
||||
+ * 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
|
||||
|
@ -1220,6 +1216,7 @@
|
|||
+#include <linux/io.h>
|
||||
+#include <linux/pm.h>
|
||||
+#include <asm/reboot.h>
|
||||
+#include <linux/module.h>
|
||||
+
|
||||
+#include <falcon.h>
|
||||
+#include <falcon/gpon_reg_base.h>
|
||||
|
@ -1232,18 +1229,25 @@
|
|||
+#define WDT_PW2 0x00DC0000
|
||||
+#define WDT_REG_BASE (KSEG1 | 0x1F8803F0)
|
||||
+
|
||||
+/* This function is used by the watchdog driver */
|
||||
+int ltq_reset_cause(void)
|
||||
+{
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(ltq_reset_cause);
|
||||
+
|
||||
+static void
|
||||
+lq_machine_restart(char *command)
|
||||
+ltq_machine_restart(char *command)
|
||||
+{
|
||||
+ printk(KERN_NOTICE "System restart\n");
|
||||
+ local_irq_disable();
|
||||
+ lq_w32(0, (void*)0xBF200000); /* reset Bootreg RVEC */
|
||||
+ ltq_w32(0, (void*)0xBF200000); /* reset Bootreg RVEC */
|
||||
+#if 0
|
||||
+ lq_w32(RBT_CPU_TRIG, &pSYS1->rbt);
|
||||
+ ltq_w32(RBT_CPU_TRIG, &pSYS1->rbt);
|
||||
+#else
|
||||
+ /* use workaround via watchdog timer */
|
||||
+ lq_w32(WDT_PW1, (void*)WDT_REG_BASE);
|
||||
+ lq_w32(WDT_PW2 |
|
||||
+ ltq_w32(WDT_PW1, (void*)WDT_REG_BASE);
|
||||
+ ltq_w32(WDT_PW2 |
|
||||
+ (0x3 << 26) | /* PWL */
|
||||
+ (0x2 << 24) | /* CLKDIV */
|
||||
+ (0x1 << 31) | /* enable */
|
||||
|
@ -1254,7 +1258,7 @@
|
|||
+}
|
||||
+
|
||||
+static void
|
||||
+lq_machine_halt(void)
|
||||
+ltq_machine_halt(void)
|
||||
+{
|
||||
+ printk(KERN_NOTICE "System halted.\n");
|
||||
+ local_irq_disable();
|
||||
|
@ -1262,7 +1266,7 @@
|
|||
+}
|
||||
+
|
||||
+static void
|
||||
+lq_machine_power_off(void)
|
||||
+ltq_machine_power_off(void)
|
||||
+{
|
||||
+ printk(KERN_NOTICE "Please turn off the power now.\n");
|
||||
+ local_irq_disable();
|
||||
|
@ -1272,16 +1276,16 @@
|
|||
+static int __init
|
||||
+mips_reboot_setup(void)
|
||||
+{
|
||||
+ _machine_restart = lq_machine_restart;
|
||||
+ _machine_halt = lq_machine_halt;
|
||||
+ pm_power_off = lq_machine_power_off;
|
||||
+ _machine_restart = ltq_machine_restart;
|
||||
+ _machine_halt = ltq_machine_halt;
|
||||
+ pm_power_off = ltq_machine_power_off;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+arch_initcall(mips_reboot_setup);
|
||||
--- /dev/null
|
||||
+++ b/arch/mips/lantiq/falcon/mach-easy98000.c
|
||||
@@ -0,0 +1,246 @@
|
||||
@@ -0,0 +1,247 @@
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/leds.h>
|
||||
|
@ -1299,7 +1303,8 @@
|
|||
+#include <linux/spi/spi.h>
|
||||
+#include <linux/spi/spi_gpio.h>
|
||||
+#include <linux/spi/eeprom.h>
|
||||
+#include <machine.h>
|
||||
+
|
||||
+#include "../machtypes.h"
|
||||
+
|
||||
+#include "devices.h"
|
||||
+#include "dev-leds-gpio.h"
|
||||
|
@ -1311,7 +1316,7 @@
|
|||
+#define EASY98000_GPIO_LED_4 13
|
||||
+#define EASY98000_GPIO_LED_5 14
|
||||
+
|
||||
+extern unsigned char lq_ethaddr[6];
|
||||
+extern unsigned char ltq_ethaddr[6];
|
||||
+
|
||||
+#ifdef CONFIG_MTD_PARTITIONS
|
||||
+static struct mtd_partition easy98000_nor_partitions[] =
|
||||
|
@ -1420,10 +1425,10 @@
|
|||
+
|
||||
+static void __init register_davicom(void)
|
||||
+{
|
||||
+ if (!is_valid_ether_addr(lq_ethaddr))
|
||||
+ if (!is_valid_ether_addr(ltq_ethaddr))
|
||||
+ random_ether_addr(dm9000_plat_data.dev_addr);
|
||||
+ else {
|
||||
+ memcpy(dm9000_plat_data.dev_addr, lq_ethaddr, 6);
|
||||
+ memcpy(dm9000_plat_data.dev_addr, ltq_ethaddr, 6);
|
||||
+ /* change to "Locally Administered Address" */
|
||||
+ dm9000_plat_data.dev_addr[0] |= 0x2;
|
||||
+ }
|
||||
|
@ -1500,7 +1505,7 @@
|
|||
+ falcon_register_i2c();
|
||||
+ platform_device_register(&easy98000_i2c_gpio_device);
|
||||
+ register_davicom();
|
||||
+ lq_add_device_leds_gpio(-1, ARRAY_SIZE(easy98000_leds_gpio),
|
||||
+ ltq_add_device_leds_gpio(-1, ARRAY_SIZE(easy98000_leds_gpio),
|
||||
+ easy98000_leds_gpio);
|
||||
+ register_easy98000_cpld_led();
|
||||
+ falcon_register_crypto();
|
||||
|
@ -1689,49 +1694,44 @@
|
|||
+#endif
|
||||
--- a/arch/mips/lantiq/Kconfig
|
||||
+++ b/arch/mips/lantiq/Kconfig
|
||||
@@ -21,16 +21,16 @@ choice
|
||||
prompt "SoC Type"
|
||||
default SOC_LANTIQ_XWAY
|
||||
|
||||
-#config SOC_LANTIQ_FALCON
|
||||
-# bool "FALCON"
|
||||
-# select SOC_LANTIQ
|
||||
+config SOC_LANTIQ_FALCON
|
||||
+ bool "FALCON"
|
||||
+ select SOC_LANTIQ
|
||||
|
||||
config SOC_LANTIQ_XWAY
|
||||
@@ -16,8 +16,12 @@
|
||||
bool "XWAY"
|
||||
select SOC_LANTIQ
|
||||
select SOC_TYPE_XWAY
|
||||
select HW_HAS_PCI
|
||||
+
|
||||
+config SOC_FALCON
|
||||
+ bool "FALCON"
|
||||
endchoice
|
||||
|
||||
-#source "arch/mips/lantiq/falcon/Kconfig"
|
||||
+source "arch/mips/lantiq/falcon/Kconfig"
|
||||
source "arch/mips/lantiq/xway/Kconfig"
|
||||
+source "arch/mips/lantiq/falcon/Kconfig"
|
||||
|
||||
if EARLY_PRINTK
|
||||
--- a/arch/mips/include/asm/mach-lantiq/machine.h
|
||||
+++ b/arch/mips/include/asm/mach-lantiq/machine.h
|
||||
@@ -5,6 +5,7 @@ enum lantiq_mach_type {
|
||||
|
||||
/* FALCON */
|
||||
LANTIQ_MACH_EASY98000, /* Falcon Eval Board, NOR Flash */
|
||||
+ LANTIQ_MACH_EASY98000SF, /* Falcon Eval Board, Serial Flash */
|
||||
LANTIQ_MACH_EASY98020, /* Falcon Reference Board */
|
||||
|
||||
/* XWAY */
|
||||
endif
|
||||
--- a/arch/mips/lantiq/Makefile
|
||||
+++ b/arch/mips/lantiq/Makefile
|
||||
@@ -1,3 +1,4 @@
|
||||
obj-y := dev-leds-gpio.o irq.o setup.o clk.o prom.o
|
||||
@@ -9,3 +9,4 @@
|
||||
obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
|
||||
+obj-$(CONFIG_SOC_LANTIQ_FALCON) += falcon/
|
||||
obj-$(CONFIG_SOC_LANTIQ_XWAY) += xway/
|
||||
|
||||
obj-$(CONFIG_SOC_TYPE_XWAY) += xway/
|
||||
+obj-$(CONFIG_SOC_FALCON) += falcon/
|
||||
--- a/arch/mips/lantiq/Platform
|
||||
+++ b/arch/mips/lantiq/Platform
|
||||
@@ -5,4 +5,5 @@
|
||||
platform-$(CONFIG_LANTIQ) += lantiq/
|
||||
cflags-$(CONFIG_LANTIQ) += -I$(srctree)/arch/mips/include/asm/mach-lantiq
|
||||
load-$(CONFIG_LANTIQ) = 0xffffffff80002000
|
||||
+cflags-$(CONFIG_SOC_LANTIQ_FALCON) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/falcon
|
||||
cflags-$(CONFIG_SOC_LANTIQ_XWAY) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/xway
|
||||
@@ -6,3 +6,4 @@
|
||||
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_FALCON) += -I$(srctree)/arch/mips/include/asm/mach-lantiq/falcon
|
||||
--- a/arch/mips/lantiq/machtypes.h
|
||||
+++ b/arch/mips/lantiq/machtypes.h
|
||||
@@ -15,6 +15,11 @@
|
||||
LTQ_MACH_GENERIC = 0,
|
||||
LTQ_MACH_EASY50712, /* Danube evaluation board */
|
||||
LTQ_MACH_EASY50601, /* Amazon SE evaluation board */
|
||||
+
|
||||
+ /* FALCON */
|
||||
+ LANTIQ_MACH_EASY98000, /* Falcon Eval Board, NOR Flash */
|
||||
+ LANTIQ_MACH_EASY98000SF, /* Falcon Eval Board, Serial Flash */
|
||||
+ LANTIQ_MACH_EASY98020, /* Falcon Reference Board */
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,15 +1,16 @@
|
|||
--- a/drivers/i2c/busses/Makefile
|
||||
+++ b/drivers/i2c/busses/Makefile
|
||||
@@ -76,5 +76,6 @@
|
||||
@@ -74,6 +74,7 @@
|
||||
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
|
||||
ifeq ($(CONFIG_I2C_DEBUG_BUS),y)
|
||||
EXTRA_CFLAGS += -DDEBUG
|
||||
--- a/drivers/i2c/busses/Kconfig
|
||||
+++ b/drivers/i2c/busses/Kconfig
|
||||
@@ -281,6 +281,10 @@
|
||||
@@ -278,6 +278,10 @@
|
||||
|
||||
comment "I2C system bus drivers (mostly embedded / system-on-chip)"
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
--- a/drivers/spi/Makefile
|
||||
+++ b/drivers/spi/Makefile
|
||||
@@ -22,6 +22,7 @@ obj-$(CONFIG_SPI_DESIGNWARE) += dw_spi.
|
||||
obj-$(CONFIG_SPI_DW_PCI) += dw_spi_pci.o
|
||||
obj-$(CONFIG_SPI_DW_MMIO) += dw_spi_mmio.o
|
||||
obj-$(CONFIG_SPI_EP93XX) += ep93xx_spi.o
|
||||
@@ -16,6 +16,7 @@
|
||||
obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o
|
||||
obj-$(CONFIG_SPI_AU1550) += au1550_spi.o
|
||||
obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o
|
||||
+obj-$(CONFIG_SPI_FALCON) += spi_falcon.o
|
||||
obj-$(CONFIG_SPI_GPIO) += spi_gpio.o
|
||||
obj-$(CONFIG_SPI_GPIO_OLD) += spi_gpio_old.o
|
||||
|
@ -484,14 +484,14 @@
|
|||
+MODULE_DESCRIPTION("Lantiq Falcon SPI controller driver");
|
||||
--- a/drivers/spi/Kconfig
|
||||
+++ b/drivers/spi/Kconfig
|
||||
@@ -169,6 +169,10 @@ config SPI_LM70_LLP
|
||||
@@ -142,6 +142,10 @@
|
||||
which interfaces to an LM70 temperature sensor using
|
||||
a parallel port.
|
||||
|
||||
+config SPI_FALCON
|
||||
+ tristate "Falcon SPI controller support"
|
||||
+ depends on SOC_LANTIQ_FALCON
|
||||
+ depends on SOC_FALCON
|
||||
+
|
||||
config SPI_MPC52xx
|
||||
tristate "Freescale MPC52xx SPI (non-PSC) controller support"
|
||||
depends on PPC_MPC52xx && SPI
|
||||
config SPI_MPC52xx_PSC
|
||||
tristate "Freescale MPC52xx PSC SPI controller"
|
||||
depends on PPC_MPC52xx && EXPERIMENTAL
|
|
@ -44,8 +44,8 @@
|
|||
+#define cpld_base7 ((u16 *)(KSEG1 | 0x17c0000c))
|
||||
+#define cpld_base8 ((u16 *)(KSEG1 | 0x17c00012))
|
||||
+
|
||||
+#define lq_r16(reg) __raw_readw(reg)
|
||||
+#define lq_w16(val, reg) __raw_writew(val, reg)
|
||||
+#define ltq_r16(reg) __raw_readw(reg)
|
||||
+#define ltq_w16(val, reg) __raw_writew(val, reg)
|
||||
+
|
||||
+struct cpld_led_dev {
|
||||
+ struct led_classdev cdev;
|
||||
|
@ -60,12 +60,12 @@
|
|||
+
|
||||
+void led_set(u8 mask, u16 *base)
|
||||
+{
|
||||
+ lq_w16(lq_r16(base) | mask, base);
|
||||
+ ltq_w16(ltq_r16(base) | mask, base);
|
||||
+}
|
||||
+
|
||||
+void led_clear(u8 mask, u16 *base)
|
||||
+{
|
||||
+ lq_w16(lq_r16(base) & (~mask), base);
|
||||
+ ltq_w16(ltq_r16(base) & (~mask), base);
|
||||
+}
|
||||
+
|
||||
+void led_blink_clear(u8 mask, u16 *base)
|
|
@ -12,7 +12,7 @@
|
|||
+#include <linux/interrupt.h>
|
||||
+#include <linux/spi/spi.h>
|
||||
+#include <linux/spi/flash.h>
|
||||
+#include <machine.h>
|
||||
+#include "../machtypes.h"
|
||||
+
|
||||
+#include "devices.h"
|
||||
+#include "dev-leds-gpio.h"
|
||||
|
@ -22,7 +22,7 @@
|
|||
+#define EASY98020_GPIO_LED_2 11
|
||||
+#define EASY98020_GPIO_LED_3 12
|
||||
+
|
||||
+extern unsigned char lq_ethaddr[6];
|
||||
+extern unsigned char ltq_ethaddr[6];
|
||||
+
|
||||
+#ifdef CONFIG_MTD_PARTITIONS
|
||||
+static struct mtd_partition easy98020_spi_partitions[] =
|
||||
|
@ -89,7 +89,7 @@
|
|||
+ falcon_register_wdt();
|
||||
+ falcon_register_i2c();
|
||||
+ falcon_register_spi_flash(&easy98020_spi_flash_data);
|
||||
+ lq_add_device_leds_gpio(-1, ARRAY_SIZE(easy98020_leds_gpio),
|
||||
+ ltq_add_device_leds_gpio(-1, ARRAY_SIZE(easy98020_leds_gpio),
|
||||
+ easy98020_leds_gpio);
|
||||
+ falcon_register_crypto();
|
||||
+}
|
||||
|
@ -100,7 +100,7 @@
|
|||
+ easy98020_init);
|
||||
--- a/arch/mips/lantiq/falcon/Kconfig
|
||||
+++ b/arch/mips/lantiq/falcon/Kconfig
|
||||
@@ -6,6 +6,10 @@ config LANTIQ_MACH_EASY98000
|
||||
@@ -6,6 +6,10 @@
|
||||
bool "Easy98000"
|
||||
default y
|
||||
|
||||
|
@ -113,7 +113,7 @@
|
|||
endif
|
||||
--- 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
|
||||
@@ -2,3 +2,4 @@
|
||||
obj-y += softdog_vpe.o
|
||||
obj-$(CONFIG_LANTIQ_MACH_EASY98000) += mach-easy98000.o
|
||||
obj-$(CONFIG_LANTIQ_MACH_EASY98000) += dev-leds-easy98000-cpld.o
|
|
@ -4,7 +4,7 @@
|
|||
+#include <linux/init.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+#include <linux/i2c-gpio.h>
|
||||
+#include <machine.h>
|
||||
+#include "../machtypes.h"
|
||||
+
|
||||
+#include "devices.h"
|
||||
+#include "dev-leds-gpio.h"
|
||||
|
@ -14,7 +14,7 @@
|
|||
+#define BOARD_95C3AM1_GPIO_LED_2 12
|
||||
+#define BOARD_95C3AM1_GPIO_LED_3 13
|
||||
+
|
||||
+extern unsigned char lq_ethaddr[6];
|
||||
+extern unsigned char ltq_ethaddr[6];
|
||||
+
|
||||
+#ifdef CONFIG_MTD_PARTITIONS
|
||||
+static struct mtd_partition board_95C3AM1_partitions[] =
|
||||
|
@ -95,7 +95,7 @@
|
|||
+ falcon_register_i2c();
|
||||
+ falcon_register_spi_flash(&board_95C3AM1_flash_data);
|
||||
+ platform_device_register(&board_95C3AM1_i2c_gpio_device);
|
||||
+ lq_add_device_leds_gpio(-1, ARRAY_SIZE(board_95C3AM1_leds_gpio),
|
||||
+ ltq_add_device_leds_gpio(-1, ARRAY_SIZE(board_95C3AM1_leds_gpio),
|
||||
+ board_95C3AM1_leds_gpio);
|
||||
+ falcon_register_crypto();
|
||||
+}
|
||||
|
@ -104,19 +104,9 @@
|
|||
+ "95C3AM1",
|
||||
+ "95C3AM1 Board",
|
||||
+ board_95C3AM1_init);
|
||||
--- a/arch/mips/include/asm/mach-lantiq/machine.h
|
||||
+++ b/arch/mips/include/asm/mach-lantiq/machine.h
|
||||
@@ -7,6 +7,7 @@ enum lantiq_mach_type {
|
||||
LANTIQ_MACH_EASY98000, /* Falcon Eval Board, NOR Flash */
|
||||
LANTIQ_MACH_EASY98000SF, /* Falcon Eval Board, Serial Flash */
|
||||
LANTIQ_MACH_EASY98020, /* Falcon Reference Board */
|
||||
+ LANTIQ_MACH_95C3AM1, /* Board 95C3AM1 */
|
||||
|
||||
/* XWAY */
|
||||
LANTIQ_MACH_EASY4010, /* Twinpass evalkit */
|
||||
--- a/arch/mips/lantiq/falcon/Kconfig
|
||||
+++ b/arch/mips/lantiq/falcon/Kconfig
|
||||
@@ -10,6 +10,10 @@ config LANTIQ_MACH_EASY98020
|
||||
@@ -10,6 +10,10 @@
|
||||
bool "Easy98020"
|
||||
default y
|
||||
|
||||
|
@ -129,8 +119,18 @@
|
|||
endif
|
||||
--- a/arch/mips/lantiq/falcon/Makefile
|
||||
+++ b/arch/mips/lantiq/falcon/Makefile
|
||||
@@ -3,3 +3,4 @@ obj-y += softdog_vpe.o
|
||||
@@ -3,3 +3,4 @@
|
||||
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
|
||||
@@ -20,6 +20,7 @@
|
||||
LANTIQ_MACH_EASY98000, /* Falcon Eval Board, NOR Flash */
|
||||
LANTIQ_MACH_EASY98000SF, /* Falcon Eval Board, Serial Flash */
|
||||
LANTIQ_MACH_EASY98020, /* Falcon Reference Board */
|
||||
+ LANTIQ_MACH_95C3AM1, /* Board 95C3AM1 */
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,25 +1,7 @@
|
|||
--- a/arch/mips/include/asm/mach-lantiq/machine.h
|
||||
+++ b/arch/mips/include/asm/mach-lantiq/machine.h
|
||||
@@ -11,4 +11,15 @@
|
||||
LANTIQ_MACH_EASY4010, /* Twinpass evalkit */
|
||||
LANTIQ_MACH_EASY50712, /* Danube evalkit */
|
||||
LANTIQ_MACH_EASY50812, /* AR9 eval board */
|
||||
+
|
||||
+ /* 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_ARV752DPW, /* Arcor easybox a802 */
|
||||
+ LANTIQ_MACH_ARV752DPW22, /* Arcor easybox a803 */
|
||||
+ LANTIQ_MACH_ARV7518PW, /* ASTORIA */
|
||||
};
|
||||
--- a/arch/mips/lantiq/xway/Kconfig
|
||||
+++ b/arch/mips/lantiq/xway/Kconfig
|
||||
@@ -14,6 +14,10 @@
|
||||
bool "Easy4010"
|
||||
@@ -6,6 +6,10 @@
|
||||
bool "Easy50712 - Danube"
|
||||
default y
|
||||
|
||||
+config LANTIQ_MACH_ARV45XX
|
||||
|
@ -31,14 +13,14 @@
|
|||
endif
|
||||
--- a/arch/mips/lantiq/xway/Makefile
|
||||
+++ b/arch/mips/lantiq/xway/Makefile
|
||||
@@ -3,3 +3,4 @@
|
||||
obj-$(CONFIG_LANTIQ_MACH_EASY50812) += mach-easy50812.o
|
||||
@@ -5,3 +5,4 @@
|
||||
|
||||
obj-$(CONFIG_LANTIQ_MACH_EASY50712) += mach-easy50712.o
|
||||
obj-$(CONFIG_LANTIQ_MACH_EASY4010) += mach-easy4010.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,537 @@
|
||||
@@ -0,0 +1,504 @@
|
||||
+/*
|
||||
+ * 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
|
||||
|
@ -60,12 +42,12 @@
|
|||
+#include <linux/ath5k_platform.h>
|
||||
+#include <linux/pci.h>
|
||||
+
|
||||
+#include <machine.h>
|
||||
+
|
||||
+#include <xway.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"
|
||||
+
|
||||
+#ifdef CONFIG_MTD_PARTITIONS
|
||||
|
@ -164,17 +146,16 @@
|
|||
+#endif
|
||||
+};
|
||||
+
|
||||
+static struct lq_pci_data lq_pci_data = {
|
||||
+ .clock = PCI_CLOCK_EXT,
|
||||
+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 lq_eth_data lq_eth_data = {
|
||||
+ .mii_mode = REV_MII_MODE,
|
||||
+ .mac = "\xff\xff\xff\xff\xff\xff",
|
||||
+static struct ltq_eth_data ltq_eth_data = {
|
||||
+ .mii_mode = PHY_INTERFACE_MODE_RMII,
|
||||
+};
|
||||
+
|
||||
+static struct gpio_led
|
||||
|
@ -191,10 +172,10 @@
|
|||
+ { .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 = 32, .active_low = 1, .default_trigger = "default-on" },
|
||||
+ { .name = "soc:green:fxs1", .gpio = 33, .active_low = 1, .default_trigger = "default-on" },
|
||||
+ { .name = "soc:green:fxs2", .gpio = 34, .active_low = 1, .default_trigger = "default-on" },
|
||||
+ { .name = "soc:green:fxo", .gpio = 35, .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_button
|
||||
|
@ -212,13 +193,13 @@
|
|||
+ { .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 = 32, .active_low = 1, },
|
||||
+ { .name = "soc:blue:fxs1", .gpio = 33, .active_low = 1, },
|
||||
+ { .name = "soc:blue:fxs2", .gpio = 34, .active_low = 1, },
|
||||
+ { .name = "soc:blue:fxo", .gpio = 35, .active_low = 1, },
|
||||
+ { .name = "soc:blue:voice", .gpio = 36, .active_low = 1, },
|
||||
+ { .name = "soc:blue:usb", .gpio = 37, .active_low = 1, },
|
||||
+ { .name = "soc:blue:wlan", .gpio = 38, .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
|
||||
|
@ -229,15 +210,15 @@
|
|||
+ { .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 = 32, .active_low = 1, .default_trigger = "default-on" },
|
||||
+ { .name = "soc:blue:fxs2", .gpio = 33, .active_low = 1, .default_trigger = "default-on" },
|
||||
+ { .name = "soc:blue:wps", .gpio = 34, .active_low = 1, .default_trigger = "default-on" },
|
||||
+ { .name = "soc:blue:fxo", .gpio = 35, .active_low = 1, .default_trigger = "default-on" },
|
||||
+ { .name = "soc:blue:voice", .gpio = 36, .active_low = 1, .default_trigger = "default-on" },
|
||||
+ { .name = "soc:blue:usb", .gpio = 37, .active_low = 1, .default_trigger = "default-on" },
|
||||
+ { .name = "soc:blue:wlan", .gpio = 38, .active_low = 1, .default_trigger = "default-on" },
|
||||
+ { .name = "soc:blue:internet", .gpio = 40, .active_low = 1, .default_trigger = "default-on" },
|
||||
+ { .name = "soc:red:internet", .gpio = 41, .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
|
||||
|
@ -255,17 +236,17 @@
|
|||
+ { .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 = 35, .active_low = 1, .default_trigger = "default-on" },
|
||||
+ { .name = "soc:red:voice", .gpio = 36, .active_low = 1, .default_trigger = "default-on" },
|
||||
+ { .name = "soc:green:usb", .gpio = 37, .active_low = 1, .default_trigger = "default-on" },
|
||||
+ { .name = "soc:green:wlan", .gpio = 38, .active_low = 1, .default_trigger = "default-on" },
|
||||
+ { .name = "soc:green:wlan1", .gpio = 39, .active_low = 1, .default_trigger = "default-on" },
|
||||
+ { .name = "soc:blue:wlan", .gpio = 40, .active_low = 1, .default_trigger = "default-on" },
|
||||
+ { .name = "soc:blue:wlan1", .gpio = 41, .active_low = 1, .default_trigger = "default-on" },
|
||||
+ { .name = "soc:green:eth1", .gpio = 43, .active_low = 1, .default_trigger = "default-on" },
|
||||
+ { .name = "soc:green:eth2", .gpio = 44, .active_low = 1, .default_trigger = "default-on" },
|
||||
+ { .name = "soc:green:eth3", .gpio = 45, .active_low = 1, .default_trigger = "default-on" },
|
||||
+ { .name = "soc:green:eth4", .gpio = 46, .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_button
|
||||
|
@ -295,27 +276,27 @@
|
|||
+arv45xx_register_ethernet(void)
|
||||
+{
|
||||
+#define ARV45XX_BRN_MAC 0x3f0016
|
||||
+ memcpy_fromio(lq_eth_data.mac,
|
||||
+ (void *)KSEG1ADDR(LQ_FLASH_START + ARV45XX_BRN_MAC), 6);
|
||||
+ lq_register_ethernet(&lq_eth_data);
|
||||
+ memcpy_fromio(<q_eth_data.mac,
|
||||
+ (void *)KSEG1ADDR(LTQ_FLASH_START + ARV45XX_BRN_MAC), 6);
|
||||
+ ltq_register_etop(<q_eth_data);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+arv75xx_register_ethernet(void)
|
||||
+{
|
||||
+#define ARV75XX_BRN_MAC 0x7f0016
|
||||
+ memcpy_fromio(lq_eth_data.mac,
|
||||
+ (void *)KSEG1ADDR(LQ_FLASH_START + ARV75XX_BRN_MAC), 6);
|
||||
+ lq_register_ethernet(&lq_eth_data);
|
||||
+ memcpy_fromio(<q_eth_data.mac,
|
||||
+ (void *)KSEG1ADDR(LTQ_FLASH_START + ARV75XX_BRN_MAC), 6);
|
||||
+ ltq_register_etop(<q_eth_data);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+bewan_register_ethernet(void)
|
||||
+{
|
||||
+#define BEWAN_BRN_MAC 0x3f0014
|
||||
+ memcpy_fromio(lq_eth_data.mac,
|
||||
+ (void *)KSEG1ADDR(LQ_FLASH_START + BEWAN_BRN_MAC), 6);
|
||||
+ lq_register_ethernet(&lq_eth_data);
|
||||
+ memcpy_fromio(<q_eth_data.mac,
|
||||
+ (void *)KSEG1ADDR(LTQ_FLASH_START + BEWAN_BRN_MAC), 6);
|
||||
+ ltq_register_etop(<q_eth_data);
|
||||
+}
|
||||
+
|
||||
+static u16 arv45xx_ath5k_eeprom_data[ATH5K_PLAT_EEP_MAX_WORDS];
|
||||
|
@ -337,10 +318,10 @@
|
|||
+ u32 *p = (u32*)arv45xx_ath5k_eeprom_data;
|
||||
+
|
||||
+ memcpy_fromio(eeprom_mac,
|
||||
+ (void *)KSEG1ADDR(LQ_FLASH_START + ARV45XX_BRN_MAC), 6);
|
||||
+ (void *)KSEG1ADDR(LTQ_FLASH_START + ARV45XX_BRN_MAC), 6);
|
||||
+ eeprom_mac[5]++;
|
||||
+ memcpy_fromio(arv45xx_ath5k_eeprom_data,
|
||||
+ (void *)KSEG1ADDR(LQ_FLASH_START + ARV45XX_BRN_ATH), ATH5K_PLAT_EEP_MAX_WORDS);
|
||||
+ (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);
|
||||
|
@ -356,19 +337,15 @@
|
|||
+ }
|
||||
+ 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;
|
||||
+ //lqpci_plat_dev_init = arv45xx_pci_plat_dev_init;
|
||||
+}
|
||||
+
|
||||
+static void __init
|
||||
+arv3527p_init(void)
|
||||
+{
|
||||
+ lq_register_gpio();
|
||||
+ lq_register_gpio_stp();
|
||||
+ //lq_register_gpio_leds(arv3527p_leds_gpio, ARRAY_SIZE(arv3527p_leds_gpio));
|
||||
+ lq_register_asc(0);
|
||||
+ lq_register_asc(1);
|
||||
+ lq_register_nor(&arv45xx_flash_data);
|
||||
+ lq_register_wdt();
|
||||
+ 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();
|
||||
+}
|
||||
+
|
||||
|
@ -380,17 +357,13 @@
|
|||
+static void __init
|
||||
+arv4510pw_init(void)
|
||||
+{
|
||||
+ lq_register_gpio();
|
||||
+ lq_register_gpio_stp();
|
||||
+ lq_register_gpio_leds(arv4510pw_leds_gpio, ARRAY_SIZE(arv4510pw_leds_gpio));
|
||||
+ lq_register_asc(0);
|
||||
+ lq_register_asc(1);
|
||||
+ lq_register_nor(&arv4510_flash_data);
|
||||
+ lq_pci_data.irq[12] = (INT_NUM_IM2_IRL0 + 31);
|
||||
+ lq_pci_data.irq[15] = (INT_NUM_IM0_IRL0 + 26);
|
||||
+ lq_pci_data.gpio |= PCI_EXIN2 | PCI_REQ2;
|
||||
+ lq_register_pci(&lq_pci_data);
|
||||
+ lq_register_wdt();
|
||||
+ 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(<q_pci_data);
|
||||
+ bewan_register_ethernet();
|
||||
+}
|
||||
+
|
||||
|
@ -406,17 +379,13 @@
|
|||
+#define ARV4518PW_USB 14
|
||||
+#define ARV4518PW_SWITCH_RESET 13
|
||||
+
|
||||
+ lq_register_gpio();
|
||||
+ lq_register_gpio_ebu(ARV4518PW_EBU);
|
||||
+ lq_register_gpio_leds(arv4518pw_leds_gpio, ARRAY_SIZE(arv4518pw_leds_gpio));
|
||||
+ lq_register_gpio_buttons(arv4518pw_gpio_buttons, ARRAY_SIZE(arv4518pw_gpio_buttons));
|
||||
+ lq_register_asc(0);
|
||||
+ lq_register_asc(1);
|
||||
+ lq_register_nor(&arv45xx_flash_data);
|
||||
+ lq_pci_data.gpio = PCI_GNT2 | PCI_REQ2;
|
||||
+ lq_register_pci(&lq_pci_data);
|
||||
+ lq_register_wdt();
|
||||
+ lq_register_madwifi_eep();
|
||||
+ ltq_register_gpio_ebu(ARV4518PW_EBU);
|
||||
+ ltq_add_device_leds_gpio(-1, ARRAY_SIZE(arv4518pw_leds_gpio), arv4518pw_leds_gpio);
|
||||
+ 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(<q_pci_data);
|
||||
+ ltq_register_madwifi_eep();
|
||||
+ xway_register_dwc(ARV4518PW_USB);
|
||||
+ arv45xx_register_ethernet();
|
||||
+ arv45xx_register_ath5k();
|
||||
|
@ -436,17 +405,13 @@
|
|||
+{
|
||||
+#define ARV4520PW_EBU 0x400
|
||||
+#define ARV4520PW_USB 28
|
||||
+#define ARV4520PW_SWITCH_RESET 42
|
||||
+#define ARV4520PW_SWITCH_RESET 82
|
||||
+
|
||||
+ lq_register_gpio();
|
||||
+ lq_register_gpio_ebu(ARV4520PW_EBU);
|
||||
+ lq_register_gpio_leds(arv4520pw_leds_gpio, ARRAY_SIZE(arv4520pw_leds_gpio));
|
||||
+ lq_register_asc(0);
|
||||
+ lq_register_asc(1);
|
||||
+ lq_register_nor(&arv45xx_flash_data);
|
||||
+ lq_register_pci(&lq_pci_data);
|
||||
+ lq_register_wdt();
|
||||
+ lq_register_tapi();
|
||||
+ 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(<q_pci_data);
|
||||
+ ltq_register_tapi();
|
||||
+ arv45xx_register_ethernet();
|
||||
+ xway_register_dwc(ARV4520PW_USB);
|
||||
+
|
||||
|
@ -465,18 +430,14 @@
|
|||
+#define ARV452CPW_EBU 0x77f
|
||||
+#define ARV452CPW_USB 28
|
||||
+#define ARV452CPW_RELAY1 31
|
||||
+#define ARV452CPW_RELAY2 39
|
||||
+#define ARV452CPW_SWITCH_RESET 42
|
||||
+#define ARV452CPW_RELAY2 79
|
||||
+#define ARV452CPW_SWITCH_RESET 82
|
||||
+
|
||||
+ lq_register_gpio();
|
||||
+ lq_register_gpio_ebu(ARV452CPW_EBU);
|
||||
+ lq_register_gpio_leds(arv452cpw_leds_gpio, ARRAY_SIZE(arv452cpw_leds_gpio));
|
||||
+ lq_register_asc(0);
|
||||
+ lq_register_asc(1);
|
||||
+ lq_register_nor(&arv45xx_flash_data);
|
||||
+ lq_register_pci(&lq_pci_data);
|
||||
+ lq_register_wdt();
|
||||
+ lq_register_madwifi_eep();
|
||||
+ 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(<q_pci_data);
|
||||
+ ltq_register_madwifi_eep();
|
||||
+ xway_register_dwc(ARV452CPW_USB);
|
||||
+ arv45xx_register_ethernet();
|
||||
+ arv45xx_register_ath5k();
|
||||
|
@ -502,16 +463,12 @@
|
|||
+static void __init
|
||||
+arv4525pw_init(void)
|
||||
+{
|
||||
+ lq_register_gpio();
|
||||
+ lq_register_gpio_leds(arv4525pw_leds_gpio, ARRAY_SIZE(arv4525pw_leds_gpio));
|
||||
+ lq_register_asc(0);
|
||||
+ lq_register_asc(1);
|
||||
+ lq_register_nor(&arv45xx_flash_data);
|
||||
+ lq_pci_data.clock = PCI_CLOCK_INT;
|
||||
+ lq_register_pci(&lq_pci_data);
|
||||
+ lq_register_wdt();
|
||||
+ lq_register_madwifi_eep();
|
||||
+ lq_eth_data.mii_mode = MII_MODE;
|
||||
+ 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(<q_pci_data);
|
||||
+ ltq_register_madwifi_eep();
|
||||
+ ltq_eth_data.mii_mode = PHY_INTERFACE_MODE_MII;
|
||||
+ arv45xx_register_ethernet();
|
||||
+}
|
||||
+
|
||||
|
@ -526,16 +483,12 @@
|
|||
+#define ARV7518PW_EBU 0x2
|
||||
+#define ARV7518PW_USB 14
|
||||
+
|
||||
+ lq_register_gpio();
|
||||
+ lq_register_gpio_ebu(ARV7518PW_EBU);
|
||||
+ lq_register_asc(0);
|
||||
+ lq_register_asc(1);
|
||||
+ lq_register_gpio_leds(arv7518pw_leds_gpio, ARRAY_SIZE(arv7518pw_leds_gpio));
|
||||
+ lq_register_gpio_buttons(arv7518pw_gpio_buttons, ARRAY_SIZE(arv7518pw_gpio_buttons));
|
||||
+ lq_register_nor(&arv75xx_flash_data);
|
||||
+ lq_register_pci(&lq_pci_data);
|
||||
+ lq_register_wdt();
|
||||
+ lq_register_tapi();
|
||||
+ ltq_register_gpio_ebu(ARV7518PW_EBU);
|
||||
+ ltq_add_device_leds_gpio(-1, ARRAY_SIZE(arv7518pw_leds_gpio), arv7518pw_leds_gpio);
|
||||
+ ltq_register_gpio_buttons(arv7518pw_gpio_buttons, ARRAY_SIZE(arv7518pw_gpio_buttons));
|
||||
+ ltq_register_nor(&arv75xx_flash_data);
|
||||
+ ltq_register_pci(<q_pci_data);
|
||||
+ ltq_register_tapi();
|
||||
+ xway_register_dwc(ARV7518PW_USB);
|
||||
+ arv75xx_register_ethernet();
|
||||
+ //arv7518_register_ath9k(mac);
|
||||
|
@ -550,20 +503,16 @@
|
|||
+arv752dpw22_init(void)
|
||||
+{
|
||||
+#define ARV752DPW22_EBU 0x2
|
||||
+#define ARV752DPW22_USB 32
|
||||
+#define ARV752DPW22_RELAY 33
|
||||
+#define ARV752DPW22_USB 72
|
||||
+#define ARV752DPW22_RELAY 73
|
||||
+
|
||||
+ lq_register_gpio();
|
||||
+ lq_register_gpio_ebu(ARV752DPW22_EBU);
|
||||
+ lq_register_asc(0);
|
||||
+ lq_register_asc(1);
|
||||
+ lq_register_gpio_leds(arv752dpw22_leds_gpio, ARRAY_SIZE(arv752dpw22_leds_gpio));
|
||||
+ lq_register_gpio_buttons(arv752dpw22_gpio_buttons, ARRAY_SIZE(arv752dpw22_gpio_buttons));
|
||||
+ lq_register_nor(&arv75xx_flash_data);
|
||||
+ lq_pci_data.irq[15] = (INT_NUM_IM2_IRL0 + 31);
|
||||
+ lq_pci_data.gpio |= PCI_EXIN1 | PCI_REQ2;
|
||||
+ lq_register_pci(&lq_pci_data);
|
||||
+ lq_register_wdt();
|
||||
+ ltq_register_gpio_ebu(ARV752DPW22_EBU);
|
||||
+ ltq_add_device_leds_gpio(-1, ARRAY_SIZE(arv752dpw22_leds_gpio), arv752dpw22_leds_gpio);
|
||||
+ 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_IM2_IRL0 + 31);
|
||||
+ ltq_pci_data.gpio |= PCI_EXIN1 | PCI_REQ2;
|
||||
+ ltq_register_pci(<q_pci_data);
|
||||
+ xway_register_dwc(ARV752DPW22_USB);
|
||||
+ arv75xx_register_ethernet();
|
||||
+
|
||||
|
@ -576,3 +525,23 @@
|
|||
+ "ARV752DPW22",
|
||||
+ "ARV752DPW22 - Arcor A803",
|
||||
+ arv752dpw22_init);
|
||||
--- a/arch/mips/lantiq/machtypes.h
|
||||
+++ b/arch/mips/lantiq/machtypes.h
|
||||
@@ -21,6 +21,17 @@
|
||||
LANTIQ_MACH_EASY98000SF, /* Falcon Eval Board, Serial 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_ARV752DPW, /* Arcor easybox a802 */
|
||||
+ LANTIQ_MACH_ARV752DPW22, /* Arcor easybox a803 */
|
||||
+ LANTIQ_MACH_ARV7518PW, /* ASTORIA */
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,6 +1,6 @@
|
|||
--- a/drivers/mtd/Kconfig
|
||||
+++ b/drivers/mtd/Kconfig
|
||||
@@ -63,6 +63,10 @@ config MTD_ROOTFS_SPLIT
|
||||
@@ -63,6 +63,10 @@
|
||||
depends on MTD_PARTITIONS
|
||||
default y
|
||||
|
||||
|
@ -13,7 +13,7 @@
|
|||
depends on MTD_PARTITIONS
|
||||
--- a/drivers/mtd/mtdpart.c
|
||||
+++ b/drivers/mtd/mtdpart.c
|
||||
@@ -722,6 +722,82 @@ static int refresh_rootfs_split(struct m
|
||||
@@ -724,6 +724,82 @@
|
||||
}
|
||||
#endif /* CONFIG_MTD_ROOTFS_SPLIT */
|
||||
|
||||
|
@ -96,7 +96,7 @@
|
|||
/*
|
||||
* 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
|
||||
@@ -746,6 +822,17 @@ int add_mtd_partitions(struct mtd_info *
|
||||
@@ -748,6 +824,17 @@
|
||||
if (!slave)
|
||||
return -ENOMEM;
|
||||
|
42
target/linux/lantiq/patches-2.6.32/220-atm_hack.patch
Normal file
42
target/linux/lantiq/patches-2.6.32/220-atm_hack.patch
Normal file
|
@ -0,0 +1,42 @@
|
|||
--- a/arch/mips/mm/cache.c
|
||||
+++ b/arch/mips/mm/cache.c
|
||||
@@ -52,6 +52,8 @@
|
||||
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
|
||||
@@ -152,7 +152,7 @@
|
||||
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
|
||||
@@ -57,11 +57,17 @@
|
||||
}
|
||||
|
||||
|
||||
+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,
|
45
target/linux/lantiq/patches-2.6.32/230-cmdline_hack.patch
Normal file
45
target/linux/lantiq/patches-2.6.32/230-cmdline_hack.patch
Normal file
|
@ -0,0 +1,45 @@
|
|||
--- a/arch/mips/lantiq/prom.c
|
||||
+++ b/arch/mips/lantiq/prom.c
|
||||
@@ -39,6 +39,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;
|
||||
@@ -53,6 +81,7 @@
|
||||
strlcat(arcs_cmdline, " ", sizeof(arcs_cmdline));
|
||||
}
|
||||
}
|
||||
+ prom_init_image_cmdline();
|
||||
}
|
||||
|
||||
void __init prom_init(void)
|
|
@ -261,18 +261,19 @@
|
|||
obj-$(CONFIG_PROC_FS) += proc.o
|
||||
--- a/net/ipv4/udp.c
|
||||
+++ b/net/ipv4/udp.c
|
||||
@@ -107,6 +107,10 @@
|
||||
@@ -106,7 +106,11 @@
|
||||
#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;
|
||||
+
|
||||
struct udp_table udp_table __read_mostly;
|
||||
EXPORT_SYMBOL(udp_table);
|
||||
|
||||
@@ -784,7 +788,7 @@
|
||||
int sysctl_udp_mem[3] __read_mostly;
|
||||
@@ -591,7 +595,7 @@
|
||||
u8 tos;
|
||||
int err, is_udplite = IS_UDPLITE(sk);
|
||||
int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
|
||||
|
@ -281,7 +282,7 @@
|
|||
|
||||
if (len > 0xFFFF)
|
||||
return -EMSGSIZE;
|
||||
@@ -946,6 +950,12 @@
|
||||
@@ -753,6 +757,12 @@
|
||||
|
||||
do_append_data:
|
||||
up->len += ulen;
|
||||
|
@ -294,7 +295,7 @@
|
|||
getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag;
|
||||
err = ip_append_data(sk, getfrag, msg->msg_iov, ulen,
|
||||
sizeof(struct udphdr), &ipc, &rt,
|
||||
@@ -1573,6 +1583,7 @@
|
||||
@@ -1283,6 +1293,7 @@
|
||||
struct rtable *rt = skb_rtable(skb);
|
||||
__be32 saddr, daddr;
|
||||
struct net *net = dev_net(skb->dev);
|
||||
|
@ -302,7 +303,7 @@
|
|||
|
||||
/*
|
||||
* Validate the packet.
|
||||
@@ -1605,7 +1616,16 @@
|
||||
@@ -1315,7 +1326,16 @@
|
||||
sk = __udp4_lib_lookup_skb(skb, uh->source, uh->dest, udptable);
|
||||
|
||||
if (sk != NULL) {
|
||||
|
@ -320,8 +321,8 @@
|
|||
sock_put(sk);
|
||||
|
||||
/* a return value > 0 means to resubmit the input, but
|
||||
@@ -1902,7 +1922,7 @@
|
||||
.clear_sk = sk_prot_clear_portaddr_nulls,
|
||||
@@ -1610,7 +1630,7 @@
|
||||
#endif
|
||||
};
|
||||
EXPORT_SYMBOL(udp_prot);
|
||||
-
|
1174
target/linux/lantiq/patches-2.6.32/250-mt-vpe.patch
Normal file
1174
target/linux/lantiq/patches-2.6.32/250-mt-vpe.patch
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
--- a/arch/mips/Kconfig
|
||||
+++ b/arch/mips/Kconfig
|
||||
@@ -1844,6 +1844,28 @@
|
||||
@@ -1653,6 +1653,28 @@
|
||||
help
|
||||
IFX included extensions in APRP
|
||||
|
||||
|
@ -31,7 +31,7 @@
|
|||
depends on MIPS_MT && PROC_FS
|
||||
--- a/arch/mips/kernel/vpe.c
|
||||
+++ b/arch/mips/kernel/vpe.c
|
||||
@@ -128,6 +128,13 @@
|
||||
@@ -129,6 +129,13 @@
|
||||
EXPORT_SYMBOL(vpe1_wdog_timeout);
|
||||
|
||||
#endif
|
||||
|
@ -45,7 +45,7 @@
|
|||
/* 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 @@
|
||||
@@ -867,6 +874,65 @@
|
||||
/* enable this VPE */
|
||||
write_vpe_c0_vpeconf0(read_vpe_c0_vpeconf0() | VPECONF0_VPA);
|
||||
|
||||
|
@ -113,7 +113,7 @@
|
|||
write_vpe_c0_cause(0);
|
||||
--- a/arch/mips/mm/c-r4k.c
|
||||
+++ b/arch/mips/mm/c-r4k.c
|
||||
@@ -1347,6 +1347,106 @@
|
||||
@@ -1348,6 +1348,106 @@
|
||||
__setup("coherentio", setcoherentio);
|
||||
#endif
|
||||
|
||||
|
@ -220,7 +220,7 @@
|
|||
void __cpuinit r4k_cache_init(void)
|
||||
{
|
||||
extern void build_clear_page(void);
|
||||
@@ -1366,6 +1466,78 @@
|
||||
@@ -1367,6 +1467,78 @@
|
||||
break;
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
--- 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
|
||||
*
|
|
@ -10,35 +10,27 @@ 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
|
||||
@@ -48,4 +48,13 @@
|
||||
|
||||
extern int (*lqpci_plat_dev_init)(struct pci_dev *dev);
|
||||
@@ -50,4 +50,13 @@
|
||||
int mii_mode;
|
||||
};
|
||||
|
||||
+
|
||||
+struct lq_spi_platform_data {
|
||||
+struct ltq_spi_platform_data {
|
||||
+ u16 num_chipselect;
|
||||
+};
|
||||
+
|
||||
+struct lq_spi_controller_data {
|
||||
+struct ltq_spi_controller_data {
|
||||
+ unsigned gpio;
|
||||
+};
|
||||
+
|
||||
#endif
|
||||
--- a/arch/mips/include/asm/mach-lantiq/xway/xway.h
|
||||
+++ b/arch/mips/include/asm/mach-lantiq/xway/xway.h
|
||||
@@ -72,6 +72,7 @@
|
||||
#define LQ_PMU_BASE_ADDR (KSEG1 + 0x1F102000)
|
||||
--- 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_SPI 0x0100
|
||||
#define PMU_USB 0x8041
|
||||
#define PMU_LED 0x0800
|
||||
#define PMU_GPT 0x1000
|
||||
@@ -105,6 +106,7 @@
|
||||
|
||||
/*------------ SSC */
|
||||
#define LQ_SSC_BASE_ADDR (KSEG1 + 0x1e100800)
|
||||
+#define LQ_SSC_SIZE 0x100
|
||||
|
||||
/*------------ MEI */
|
||||
#define LQ_MEI_BASE_ADDR (KSEG1 + 0x1E116000)
|
||||
#define PMU_DMA 0x0020
|
||||
#define PMU_USB 0x8041
|
||||
+#define PMU_SPI 0x0100
|
||||
#define PMU_LED 0x0800
|
||||
#define PMU_GPT 0x1000
|
||||
#define PMU_PPE 0x2000
|
1103
target/linux/lantiq/patches-2.6.32/410-spi2.patch
Normal file
1103
target/linux/lantiq/patches-2.6.32/410-spi2.patch
Normal file
File diff suppressed because it is too large
Load diff
49
target/linux/lantiq/patches-2.6.32/420-spi3.patch
Normal file
49
target/linux/lantiq/patches-2.6.32/420-spi3.patch
Normal file
|
@ -0,0 +1,49 @@
|
|||
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,28 @@
|
||||
platform_device_register(<q_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 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)
|
||||
+{
|
||||
+ spi_register_board_info(info, n);
|
||||
+ ltq_spi.dev.platform_data = pdata;
|
||||
+ platform_device_register(<q_spi);
|
||||
+}
|
41
target/linux/lantiq/patches-2.6.32/500-register_ebu.patch
Normal file
41
target/linux/lantiq/patches-2.6.32/500-register_ebu.patch
Normal file
|
@ -0,0 +1,41 @@
|
|||
--- a/arch/mips/lantiq/xway/devices.c
|
||||
+++ b/arch/mips/lantiq/xway/devices.c
|
||||
@@ -121,6 +121,29 @@
|
||||
}
|
||||
}
|
||||
|
||||
+/* 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 = <q_ebu_resource,
|
||||
+ .num_resources = 1,
|
||||
+};
|
||||
+
|
||||
+void __init
|
||||
+ltq_register_gpio_ebu(unsigned int value)
|
||||
+{
|
||||
+ ltq_ebu.dev.platform_data = (void*) value;
|
||||
+ platform_device_register(<q_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_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
|
|
@ -0,0 +1,28 @@
|
|||
--- a/arch/mips/lantiq/xway/devices.c
|
||||
+++ b/arch/mips/lantiq/xway/devices.c
|
||||
@@ -144,6 +144,16 @@
|
||||
platform_device_register(<q_ebu);
|
||||
}
|
||||
|
||||
+/* madwifi */
|
||||
+int lantiq_emulate_madwifi_eep = 0;
|
||||
+EXPORT_SYMBOL(lantiq_emulate_madwifi_eep);
|
||||
+
|
||||
+void __init
|
||||
+ltq_register_madwifi_eep(void)
|
||||
+{
|
||||
+ lantiq_emulate_madwifi_eep = 1;
|
||||
+}
|
||||
+
|
||||
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_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(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,46 @@
|
|||
--- a/arch/mips/lantiq/xway/devices.c
|
||||
+++ b/arch/mips/lantiq/xway/devices.c
|
||||
@@ -154,6 +154,26 @@
|
||||
lantiq_emulate_madwifi_eep = 1;
|
||||
}
|
||||
|
||||
+/* gpio buttons */
|
||||
+static struct gpio_buttons_platform_data ltq_gpio_buttons_platform_data;
|
||||
+
|
||||
+static struct platform_device ltq_gpio_buttons_platform_device =
|
||||
+{
|
||||
+ .name = "gpio-buttons",
|
||||
+ .id = 0,
|
||||
+ .dev = {
|
||||
+ .platform_data = (void *) <q_gpio_buttons_platform_data,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+void __init
|
||||
+ltq_register_gpio_buttons(struct gpio_button *buttons, int cnt)
|
||||
+{
|
||||
+ ltq_gpio_buttons_platform_data.buttons = buttons;
|
||||
+ ltq_gpio_buttons_platform_data.nbuttons = cnt;
|
||||
+ platform_device_register(<q_gpio_buttons_platform_device);
|
||||
+}
|
||||
+
|
||||
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
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "../devices.h"
|
||||
#include <linux/phy.h>
|
||||
+#include <linux/gpio_buttons.h>
|
||||
|
||||
extern void ltq_register_gpio(void);
|
||||
extern void ltq_register_gpio_stp(void);
|
||||
@@ -18,5 +19,6 @@
|
||||
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(void);
|
||||
+extern void ltq_register_gpio_buttons(struct gpio_button *buttons, int cnt);
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue