aboutsummaryrefslogtreecommitdiff
path: root/arch/m68k/atari
diff options
context:
space:
mode:
Diffstat (limited to 'arch/m68k/atari')
-rw-r--r--arch/m68k/atari/ataints.c156
-rw-r--r--arch/m68k/atari/config.c253
-rw-r--r--arch/m68k/atari/debug.c5
-rw-r--r--arch/m68k/atari/stram.c71
-rw-r--r--arch/m68k/atari/time.c6
5 files changed, 464 insertions, 27 deletions
diff --git a/arch/m68k/atari/ataints.c b/arch/m68k/atari/ataints.c
index 3f41092d1b7..3d2b63bedf0 100644
--- a/arch/m68k/atari/ataints.c
+++ b/arch/m68k/atari/ataints.c
@@ -41,6 +41,7 @@
#include <linux/init.h>
#include <linux/seq_file.h>
#include <linux/module.h>
+#include <linux/irq.h>
#include <asm/traps.h>
@@ -49,6 +50,7 @@
#include <asm/atari_stdma.h>
#include <asm/irq.h>
#include <asm/entry.h>
+#include <asm/io.h>
/*
@@ -122,6 +124,136 @@ static struct irq_chip atari_irq_chip = {
};
/*
+ * ST-MFP timer D chained interrupts - each driver gets its own timer
+ * interrupt instance.
+ */
+
+struct mfptimerbase {
+ volatile struct MFP *mfp;
+ unsigned char mfp_mask, mfp_data;
+ unsigned short int_mask;
+ int handler_irq, mfptimer_irq, server_irq;
+ char *name;
+} stmfp_base = {
+ .mfp = &st_mfp,
+ .int_mask = 0x0,
+ .handler_irq = IRQ_MFP_TIMD,
+ .mfptimer_irq = IRQ_MFP_TIMER1,
+ .name = "MFP Timer D"
+};
+
+static irqreturn_t mfptimer_handler(int irq, void *dev_id)
+{
+ struct mfptimerbase *base = dev_id;
+ int mach_irq;
+ unsigned char ints;
+
+ mach_irq = base->mfptimer_irq;
+ ints = base->int_mask;
+ for (; ints; mach_irq++, ints >>= 1) {
+ if (ints & 1)
+ generic_handle_irq(mach_irq);
+ }
+ return IRQ_HANDLED;
+}
+
+
+static void atari_mfptimer_enable(struct irq_data *data)
+{
+ int mfp_num = data->irq - IRQ_MFP_TIMER1;
+ stmfp_base.int_mask |= 1 << mfp_num;
+ atari_enable_irq(IRQ_MFP_TIMD);
+}
+
+static void atari_mfptimer_disable(struct irq_data *data)
+{
+ int mfp_num = data->irq - IRQ_MFP_TIMER1;
+ stmfp_base.int_mask &= ~(1 << mfp_num);
+ if (!stmfp_base.int_mask)
+ atari_disable_irq(IRQ_MFP_TIMD);
+}
+
+static struct irq_chip atari_mfptimer_chip = {
+ .name = "timer_d",
+ .irq_enable = atari_mfptimer_enable,
+ .irq_disable = atari_mfptimer_disable,
+};
+
+
+/*
+ * EtherNAT CPLD interrupt handling
+ * CPLD interrupt register is at phys. 0x80000023
+ * Need this mapped in at interrupt startup time
+ * Possibly need this mapped on demand anyway -
+ * EtherNAT USB driver needs to disable IRQ before
+ * startup!
+ */
+
+static unsigned char *enat_cpld;
+
+static unsigned int atari_ethernat_startup(struct irq_data *data)
+{
+ int enat_num = 140 - data->irq + 1;
+
+ m68k_irq_startup(data);
+ /*
+ * map CPLD interrupt register
+ */
+ if (!enat_cpld)
+ enat_cpld = (unsigned char *)ioremap((ATARI_ETHERNAT_PHYS_ADDR+0x23), 0x2);
+ /*
+ * do _not_ enable the USB chip interrupt here - causes interrupt storm
+ * and triggers dead interrupt watchdog
+ * Need to reset the USB chip to a sane state in early startup before
+ * removing this hack
+ */
+ if (enat_num == 1)
+ *enat_cpld |= 1 << enat_num;
+
+ return 0;
+}
+
+static void atari_ethernat_enable(struct irq_data *data)
+{
+ int enat_num = 140 - data->irq + 1;
+ /*
+ * map CPLD interrupt register
+ */
+ if (!enat_cpld)
+ enat_cpld = (unsigned char *)ioremap((ATARI_ETHERNAT_PHYS_ADDR+0x23), 0x2);
+ *enat_cpld |= 1 << enat_num;
+}
+
+static void atari_ethernat_disable(struct irq_data *data)
+{
+ int enat_num = 140 - data->irq + 1;
+ /*
+ * map CPLD interrupt register
+ */
+ if (!enat_cpld)
+ enat_cpld = (unsigned char *)ioremap((ATARI_ETHERNAT_PHYS_ADDR+0x23), 0x2);
+ *enat_cpld &= ~(1 << enat_num);
+}
+
+static void atari_ethernat_shutdown(struct irq_data *data)
+{
+ int enat_num = 140 - data->irq + 1;
+ if (enat_cpld) {
+ *enat_cpld &= ~(1 << enat_num);
+ iounmap(enat_cpld);
+ enat_cpld = NULL;
+ }
+}
+
+static struct irq_chip atari_ethernat_chip = {
+ .name = "ethernat",
+ .irq_startup = atari_ethernat_startup,
+ .irq_shutdown = atari_ethernat_shutdown,
+ .irq_enable = atari_ethernat_enable,
+ .irq_disable = atari_ethernat_disable,
+};
+
+/*
* void atari_init_IRQ (void)
*
* Parameters: None
@@ -198,6 +330,30 @@ void __init atari_init_IRQ(void)
/* Initialize the PSG: all sounds off, both ports output */
sound_ym.rd_data_reg_sel = 7;
sound_ym.wd_data = 0xff;
+
+ m68k_setup_irq_controller(&atari_mfptimer_chip, handle_simple_irq,
+ IRQ_MFP_TIMER1, 8);
+
+ irq_set_status_flags(IRQ_MFP_TIMER1, IRQ_IS_POLLED);
+ irq_set_status_flags(IRQ_MFP_TIMER2, IRQ_IS_POLLED);
+
+ /* prepare timer D data for use as poll interrupt */
+ /* set Timer D data Register - needs to be > 0 */
+ st_mfp.tim_dt_d = 254; /* < 100 Hz */
+ /* start timer D, div = 1:100 */
+ st_mfp.tim_ct_cd = (st_mfp.tim_ct_cd & 0xf0) | 0x6;
+
+ /* request timer D dispatch handler */
+ if (request_irq(IRQ_MFP_TIMD, mfptimer_handler, IRQF_SHARED,
+ stmfp_base.name, &stmfp_base))
+ pr_err("Couldn't register %s interrupt\n", stmfp_base.name);
+
+ /*
+ * EtherNAT ethernet / USB interrupt handlers
+ */
+
+ m68k_setup_irq_controller(&atari_ethernat_chip, handle_simple_irq,
+ 139, 2);
}
diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c
index d8eb32747ac..01a62161b08 100644
--- a/arch/m68k/atari/config.c
+++ b/arch/m68k/atari/config.c
@@ -31,10 +31,14 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/usb/isp116x.h>
#include <linux/vt_kern.h>
#include <linux/module.h>
#include <asm/bootinfo.h>
+#include <asm/bootinfo-atari.h>
+#include <asm/byteorder.h>
#include <asm/setup.h>
#include <asm/atarihw.h>
#include <asm/atariints.h>
@@ -74,7 +78,7 @@ static void atari_heartbeat(int on);
/* atari specific timer functions (in time.c) */
extern void atari_sched_init(irq_handler_t);
-extern unsigned long atari_gettimeoffset (void);
+extern u32 atari_gettimeoffset(void);
extern int atari_mste_hwclk (int, struct rtc_time *);
extern int atari_tt_hwclk (int, struct rtc_time *);
extern int atari_mste_set_clock_mmss (unsigned long);
@@ -127,14 +131,14 @@ static int __init scc_test(volatile char *ctla)
int __init atari_parse_bootinfo(const struct bi_record *record)
{
int unknown = 0;
- const u_long *data = record->data;
+ const void *data = record->data;
- switch (record->tag) {
+ switch (be16_to_cpu(record->tag)) {
case BI_ATARI_MCH_COOKIE:
- atari_mch_cookie = *data;
+ atari_mch_cookie = be32_to_cpup(data);
break;
case BI_ATARI_MCH_TYPE:
- atari_mch_type = *data;
+ atari_mch_type = be32_to_cpup(data);
break;
default:
unknown = 1;
@@ -204,7 +208,7 @@ void __init config_atari(void)
mach_init_IRQ = atari_init_IRQ;
mach_get_model = atari_get_model;
mach_get_hardware_list = atari_get_hardware_list;
- mach_gettimeoffset = atari_gettimeoffset;
+ arch_gettimeoffset = atari_gettimeoffset;
mach_reset = atari_reset;
mach_max_dma_address = 0xffffff;
#if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
@@ -655,3 +659,240 @@ static void atari_get_hardware_list(struct seq_file *m)
ATARIHW_ANNOUNCE(VME, "VME Bus");
ATARIHW_ANNOUNCE(DSP56K, "DSP56001 processor");
}
+
+/*
+ * MSch: initial platform device support for Atari,
+ * required for EtherNAT/EtherNEC/NetUSBee drivers
+ */
+
+#if defined(CONFIG_ATARI_ETHERNAT) || defined(CONFIG_ATARI_ETHERNEC)
+static void isp1160_delay(struct device *dev, int delay)
+{
+ ndelay(delay);
+}
+#endif
+
+#ifdef CONFIG_ATARI_ETHERNAT
+/*
+ * EtherNAT: SMC91C111 Ethernet chipset, handled by smc91x driver
+ */
+
+#define ATARI_ETHERNAT_IRQ 140
+
+static struct resource smc91x_resources[] = {
+ [0] = {
+ .name = "smc91x-regs",
+ .start = ATARI_ETHERNAT_PHYS_ADDR,
+ .end = ATARI_ETHERNAT_PHYS_ADDR + 0xfffff,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "smc91x-irq",
+ .start = ATARI_ETHERNAT_IRQ,
+ .end = ATARI_ETHERNAT_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device smc91x_device = {
+ .name = "smc91x",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(smc91x_resources),
+ .resource = smc91x_resources,
+};
+
+/*
+ * ISP 1160 - using the isp116x-hcd module
+ */
+
+#define ATARI_USB_PHYS_ADDR 0x80000012
+#define ATARI_USB_IRQ 139
+
+static struct resource isp1160_resources[] = {
+ [0] = {
+ .name = "isp1160-data",
+ .start = ATARI_USB_PHYS_ADDR,
+ .end = ATARI_USB_PHYS_ADDR + 0x1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "isp1160-regs",
+ .start = ATARI_USB_PHYS_ADDR + 0x4,
+ .end = ATARI_USB_PHYS_ADDR + 0x5,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .name = "isp1160-irq",
+ .start = ATARI_USB_IRQ,
+ .end = ATARI_USB_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+/* (DataBusWidth16|AnalogOCEnable|DREQOutputPolarity|DownstreamPort15KRSel ) */
+static struct isp116x_platform_data isp1160_platform_data = {
+ /* Enable internal resistors on downstream ports */
+ .sel15Kres = 1,
+ /* On-chip overcurrent protection */
+ .oc_enable = 1,
+ /* INT output polarity */
+ .int_act_high = 1,
+ /* INT edge or level triggered */
+ .int_edge_triggered = 0,
+
+ /* WAKEUP pin connected - NOT SUPPORTED */
+ /* .remote_wakeup_connected = 0, */
+ /* Wakeup by devices on usb bus enabled */
+ .remote_wakeup_enable = 0,
+ .delay = isp1160_delay,
+};
+
+static struct platform_device isp1160_device = {
+ .name = "isp116x-hcd",
+ .id = 0,
+ .num_resources = ARRAY_SIZE(isp1160_resources),
+ .resource = isp1160_resources,
+ .dev = {
+ .platform_data = &isp1160_platform_data,
+ },
+};
+
+static struct platform_device *atari_ethernat_devices[] __initdata = {
+ &smc91x_device,
+ &isp1160_device
+};
+#endif /* CONFIG_ATARI_ETHERNAT */
+
+#ifdef CONFIG_ATARI_ETHERNEC
+/*
+ * EtherNEC: RTL8019 (NE2000 compatible) Ethernet chipset,
+ * handled by ne.c driver
+ */
+
+#define ATARI_ETHERNEC_PHYS_ADDR 0xfffa0000
+#define ATARI_ETHERNEC_BASE 0x300
+#define ATARI_ETHERNEC_IRQ IRQ_MFP_TIMER1
+
+static struct resource rtl8019_resources[] = {
+ [0] = {
+ .name = "rtl8019-regs",
+ .start = ATARI_ETHERNEC_BASE,
+ .end = ATARI_ETHERNEC_BASE + 0x20 - 1,
+ .flags = IORESOURCE_IO,
+ },
+ [1] = {
+ .name = "rtl8019-irq",
+ .start = ATARI_ETHERNEC_IRQ,
+ .end = ATARI_ETHERNEC_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+static struct platform_device rtl8019_device = {
+ .name = "ne",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(rtl8019_resources),
+ .resource = rtl8019_resources,
+};
+
+/*
+ * NetUSBee: ISP1160 USB host adapter via ROM-port adapter
+ */
+
+#define ATARI_NETUSBEE_PHYS_ADDR 0xfffa8000
+#define ATARI_NETUSBEE_BASE 0x340
+#define ATARI_NETUSBEE_IRQ IRQ_MFP_TIMER2
+
+static struct resource netusbee_resources[] = {
+ [0] = {
+ .name = "isp1160-data",
+ .start = ATARI_NETUSBEE_BASE,
+ .end = ATARI_NETUSBEE_BASE + 0x1,
+ .flags = IORESOURCE_MEM,
+ },
+ [1] = {
+ .name = "isp1160-regs",
+ .start = ATARI_NETUSBEE_BASE + 0x20,
+ .end = ATARI_NETUSBEE_BASE + 0x21,
+ .flags = IORESOURCE_MEM,
+ },
+ [2] = {
+ .name = "isp1160-irq",
+ .start = ATARI_NETUSBEE_IRQ,
+ .end = ATARI_NETUSBEE_IRQ,
+ .flags = IORESOURCE_IRQ,
+ },
+};
+
+/* (DataBusWidth16|AnalogOCEnable|DREQOutputPolarity|DownstreamPort15KRSel ) */
+static struct isp116x_platform_data netusbee_platform_data = {
+ /* Enable internal resistors on downstream ports */
+ .sel15Kres = 1,
+ /* On-chip overcurrent protection */
+ .oc_enable = 1,
+ /* INT output polarity */
+ .int_act_high = 1,
+ /* INT edge or level triggered */
+ .int_edge_triggered = 0,
+
+ /* WAKEUP pin connected - NOT SUPPORTED */
+ /* .remote_wakeup_connected = 0, */
+ /* Wakeup by devices on usb bus enabled */
+ .remote_wakeup_enable = 0,
+ .delay = isp1160_delay,
+};
+
+static struct platform_device netusbee_device = {
+ .name = "isp116x-hcd",
+ .id = 1,
+ .num_resources = ARRAY_SIZE(netusbee_resources),
+ .resource = netusbee_resources,
+ .dev = {
+ .platform_data = &netusbee_platform_data,
+ },
+};
+
+static struct platform_device *atari_netusbee_devices[] __initdata = {
+ &rtl8019_device,
+ &netusbee_device
+};
+#endif /* CONFIG_ATARI_ETHERNEC */
+
+int __init atari_platform_init(void)
+{
+ int rv = 0;
+
+ if (!MACH_IS_ATARI)
+ return -ENODEV;
+
+#ifdef CONFIG_ATARI_ETHERNAT
+ {
+ unsigned char *enatc_virt;
+ enatc_virt = (unsigned char *)ioremap((ATARI_ETHERNAT_PHYS_ADDR+0x23), 0xf);
+ if (hwreg_present(enatc_virt)) {
+ rv = platform_add_devices(atari_ethernat_devices,
+ ARRAY_SIZE(atari_ethernat_devices));
+ }
+ iounmap(enatc_virt);
+ }
+#endif
+
+#ifdef CONFIG_ATARI_ETHERNEC
+ {
+ int error;
+ unsigned char *enec_virt;
+ enec_virt = (unsigned char *)ioremap((ATARI_ETHERNEC_PHYS_ADDR), 0xf);
+ if (hwreg_present(enec_virt)) {
+ error = platform_add_devices(atari_netusbee_devices,
+ ARRAY_SIZE(atari_netusbee_devices));
+ if (error && !rv)
+ rv = error;
+ }
+ iounmap(enec_virt);
+ }
+#endif
+
+ return rv;
+}
+
+arch_initcall(atari_platform_init);
diff --git a/arch/m68k/atari/debug.c b/arch/m68k/atari/debug.c
index a547ba9683d..03cb5e08d7c 100644
--- a/arch/m68k/atari/debug.c
+++ b/arch/m68k/atari/debug.c
@@ -287,6 +287,8 @@ static void __init atari_init_midi_port(int cflag)
static int __init atari_debug_setup(char *arg)
{
+ bool registered;
+
if (!MACH_IS_ATARI)
return 0;
@@ -294,6 +296,7 @@ static int __init atari_debug_setup(char *arg)
/* defaults to ser2 for a Falcon and ser1 otherwise */
arg = MACH_IS_FALCON ? "ser2" : "ser1";
+ registered = !!atari_console_driver.write;
if (!strcmp(arg, "ser1")) {
/* ST-MFP Modem1 serial port */
atari_init_mfp_port(B9600|CS8);
@@ -317,7 +320,7 @@ static int __init atari_debug_setup(char *arg)
sound_ym.wd_data = sound_ym.rd_data_reg_sel | 0x20; /* strobe H */
atari_console_driver.write = atari_par_console_write;
}
- if (atari_console_driver.write)
+ if (atari_console_driver.write && !registered)
register_console(&atari_console_driver);
return 0;
diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c
index 0810c8d56e5..5f8cb5a234d 100644
--- a/arch/m68k/atari/stram.c
+++ b/arch/m68k/atari/stram.c
@@ -47,6 +47,7 @@ static struct resource stram_pool = {
static unsigned long pool_size = 1024*1024;
+static unsigned long stram_virt_offset;
static int __init atari_stram_setup(char *arg)
{
@@ -67,14 +68,12 @@ early_param("stram_pool", atari_stram_setup);
void __init atari_stram_init(void)
{
int i;
- void *stram_start;
/*
* determine whether kernel code resides in ST-RAM
* (then ST-RAM is the first memory block at virtual 0x0)
*/
- stram_start = phys_to_virt(0);
- kernel_in_stram = (stram_start == 0);
+ kernel_in_stram = (m68k_memory[0].addr == 0);
for (i = 0; i < m68k_num_memory; ++i) {
if (m68k_memory[i].addr == 0) {
@@ -89,24 +88,62 @@ void __init atari_stram_init(void)
/*
* This function is called from setup_arch() to reserve the pages needed for
- * ST-RAM management.
+ * ST-RAM management, if the kernel resides in ST-RAM.
*/
void __init atari_stram_reserve_pages(void *start_mem)
{
- /*
- * always reserve first page of ST-RAM, the first 2 KiB are
- * supervisor-only!
- */
- if (!kernel_in_stram)
- reserve_bootmem(0, PAGE_SIZE, BOOTMEM_DEFAULT);
+ if (kernel_in_stram) {
+ pr_debug("atari_stram pool: kernel in ST-RAM, using alloc_bootmem!\n");
+ stram_pool.start = (resource_size_t)alloc_bootmem_low_pages(pool_size);
+ stram_pool.end = stram_pool.start + pool_size - 1;
+ request_resource(&iomem_resource, &stram_pool);
+ stram_virt_offset = 0;
+ pr_debug("atari_stram pool: size = %lu bytes, resource = %pR\n",
+ pool_size, &stram_pool);
+ pr_debug("atari_stram pool: stram_virt_offset = %lx\n",
+ stram_virt_offset);
+ }
+}
- stram_pool.start = (resource_size_t)alloc_bootmem_low_pages(pool_size);
- stram_pool.end = stram_pool.start + pool_size - 1;
- request_resource(&iomem_resource, &stram_pool);
- pr_debug("atari_stram pool: size = %lu bytes, resource = %pR\n",
- pool_size, &stram_pool);
+/*
+ * This function is called as arch initcall to reserve the pages needed for
+ * ST-RAM management, if the kernel does not reside in ST-RAM.
+ */
+int __init atari_stram_map_pages(void)
+{
+ if (!kernel_in_stram) {
+ /*
+ * Skip page 0, as the fhe first 2 KiB are supervisor-only!
+ */
+ pr_debug("atari_stram pool: kernel not in ST-RAM, using ioremap!\n");
+ stram_pool.start = PAGE_SIZE;
+ stram_pool.end = stram_pool.start + pool_size - 1;
+ request_resource(&iomem_resource, &stram_pool);
+ stram_virt_offset = (unsigned long) ioremap(stram_pool.start,
+ resource_size(&stram_pool)) - stram_pool.start;
+ pr_debug("atari_stram pool: size = %lu bytes, resource = %pR\n",
+ pool_size, &stram_pool);
+ pr_debug("atari_stram pool: stram_virt_offset = %lx\n",
+ stram_virt_offset);
+ }
+ return 0;
+}
+arch_initcall(atari_stram_map_pages);
+
+
+void *atari_stram_to_virt(unsigned long phys)
+{
+ return (void *)(phys + stram_virt_offset);
+}
+EXPORT_SYMBOL(atari_stram_to_virt);
+
+
+unsigned long atari_stram_to_phys(void *virt)
+{
+ return (unsigned long)(virt - stram_virt_offset);
}
+EXPORT_SYMBOL(atari_stram_to_phys);
void *atari_stram_alloc(unsigned long size, const char *owner)
@@ -134,14 +171,14 @@ void *atari_stram_alloc(unsigned long size, const char *owner)
}
pr_debug("atari_stram_alloc: returning %pR\n", res);
- return (void *)res->start;
+ return atari_stram_to_virt(res->start);
}
EXPORT_SYMBOL(atari_stram_alloc);
void atari_stram_free(void *addr)
{
- unsigned long start = (unsigned long)addr;
+ unsigned long start = atari_stram_to_phys(addr);
struct resource *res;
unsigned long size;
diff --git a/arch/m68k/atari/time.c b/arch/m68k/atari/time.c
index c0cc68a2c82..da8f981c36d 100644
--- a/arch/m68k/atari/time.c
+++ b/arch/m68k/atari/time.c
@@ -42,9 +42,9 @@ atari_sched_init(irq_handler_t timer_routine)
#define TICK_SIZE 10000
/* This is always executed with interrupts disabled. */
-unsigned long atari_gettimeoffset (void)
+u32 atari_gettimeoffset(void)
{
- unsigned long ticks, offset = 0;
+ u32 ticks, offset = 0;
/* read MFP timer C current value */
ticks = st_mfp.tim_dt_c;
@@ -57,7 +57,7 @@ unsigned long atari_gettimeoffset (void)
ticks = INT_TICKS - ticks;
ticks = ticks * 10000L / INT_TICKS;
- return ticks + offset;
+ return (ticks + offset) * 1000;
}