Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 851d4f5d authored by Manuel Lauss's avatar Manuel Lauss Committed by Ralf Baechle
Browse files

MIPS: Alchemy: Merge PB1100/1500 support into DB1000 code.



The PB1100/1500 are similar to their DB-cousins but with a few
more devices on the bus.

This patch adds PB1100/1500 support to the existing DB1100/1500
code.

Signed-off-by: default avatarManuel Lauss <manuel.lauss@gmail.com>
Cc: lnux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/4338/


Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent 24e8c1a6
Loading
Loading
Loading
Loading
+1 −18
Original line number Original line Diff line number Diff line
@@ -27,7 +27,7 @@ config MIPS_MTX1
	select SYS_HAS_EARLY_PRINTK
	select SYS_HAS_EARLY_PRINTK


config MIPS_DB1000
config MIPS_DB1000
	bool "Alchemy DB1000/DB1500/DB1100 boards"
	bool "Alchemy DB1000/DB1500/DB1100 PB1500/1100 boards"
	select ALCHEMY_GPIOINT_AU1000
	select ALCHEMY_GPIOINT_AU1000
	select DMA_NONCOHERENT
	select DMA_NONCOHERENT
	select HW_HAS_PCI
	select HW_HAS_PCI
@@ -45,23 +45,6 @@ config MIPS_DB1235
	select SYS_SUPPORTS_LITTLE_ENDIAN
	select SYS_SUPPORTS_LITTLE_ENDIAN
	select SYS_HAS_EARLY_PRINTK
	select SYS_HAS_EARLY_PRINTK


config MIPS_PB1100
	bool "Alchemy PB1100 board"
	select ALCHEMY_GPIOINT_AU1000
	select DMA_NONCOHERENT
	select HW_HAS_PCI
	select SWAP_IO_SPACE
	select SYS_SUPPORTS_LITTLE_ENDIAN
	select SYS_HAS_EARLY_PRINTK

config MIPS_PB1500
	bool "Alchemy PB1500 board"
	select ALCHEMY_GPIOINT_AU1000
	select DMA_NONCOHERENT
	select HW_HAS_PCI
	select SYS_SUPPORTS_LITTLE_ENDIAN
	select SYS_HAS_EARLY_PRINTK

config MIPS_XXS1500
config MIPS_XXS1500
	bool "MyCable XXS1500 board"
	bool "MyCable XXS1500 board"
	select DMA_NONCOHERENT
	select DMA_NONCOHERENT
+0 −2
Original line number Original line Diff line number Diff line
@@ -4,7 +4,5 @@


obj-y += bcsr.o platform.o
obj-y += bcsr.o platform.o
obj-$(CONFIG_PM)		+= pm.o
obj-$(CONFIG_PM)		+= pm.o
obj-$(CONFIG_MIPS_PB1100)	+= pb1100.o
obj-$(CONFIG_MIPS_PB1500)	+= pb1500.o
obj-$(CONFIG_MIPS_DB1000)	+= db1000.o
obj-$(CONFIG_MIPS_DB1000)	+= db1000.o
obj-$(CONFIG_MIPS_DB1235)	+= db1235.o db1200.o db1300.o db1550.o
obj-$(CONFIG_MIPS_DB1235)	+= db1235.o db1200.o db1300.o db1550.o
+92 −28
Original line number Original line Diff line number Diff line
/*
/*
 * DBAu1000/1500/1100 board support
 * DBAu1000/1500/1100 PBAu1100/1500 board support
 *
 *
 * Copyright 2000, 2008 MontaVista Software Inc.
 * Copyright 2000, 2008 MontaVista Software Inc.
 * Author: MontaVista Software, Inc. <source@mvista.com>
 * Author: MontaVista Software, Inc. <source@mvista.com>
@@ -52,6 +52,11 @@ static const char *board_type_str(void)
		return "DB1500";
		return "DB1500";
	case BCSR_WHOAMI_DB1100:
	case BCSR_WHOAMI_DB1100:
		return "DB1100";
		return "DB1100";
	case BCSR_WHOAMI_PB1500:
	case BCSR_WHOAMI_PB1500R2:
		return "PB1500";
	case BCSR_WHOAMI_PB1100:
		return "PB1100";
	default:
	default:
		return "(unknown)";
		return "(unknown)";
	}
	}
@@ -111,7 +116,9 @@ static struct platform_device db1500_pci_host_dev = {


static int __init db1500_pci_init(void)
static int __init db1500_pci_init(void)
{
{
	if (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI)) == BCSR_WHOAMI_DB1500)
	int id = BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI));
	if ((id == BCSR_WHOAMI_DB1500) || (id == BCSR_WHOAMI_PB1500) ||
	    (id == BCSR_WHOAMI_PB1500R2))
		return platform_device_register(&db1500_pci_host_dev);
		return platform_device_register(&db1500_pci_host_dev);
	return 0;
	return 0;
}
}
@@ -199,27 +206,37 @@ static irqreturn_t db1100_mmc_cd(int irq, void *ptr)


static int db1100_mmc_cd_setup(void *mmc_host, int en)
static int db1100_mmc_cd_setup(void *mmc_host, int en)
{
{
	int ret = 0;
	int ret = 0, irq;

	if (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI)) == BCSR_WHOAMI_DB1100)
		irq = AU1100_GPIO19_INT;
	else
		irq = AU1100_GPIO14_INT;	/* PB1100 SD0 CD# */


	if (en) {
	if (en) {
		irq_set_irq_type(AU1100_GPIO19_INT, IRQ_TYPE_EDGE_BOTH);
		irq_set_irq_type(irq, IRQ_TYPE_EDGE_BOTH);
		ret = request_irq(AU1100_GPIO19_INT, db1100_mmc_cd, 0,
		ret = request_irq(irq, db1100_mmc_cd, 0,
				  "sd0_cd", mmc_host);
				  "sd0_cd", mmc_host);
	} else
	} else
		free_irq(AU1100_GPIO19_INT, mmc_host);
		free_irq(irq, mmc_host);
	return ret;
	return ret;
}
}


static int db1100_mmc1_cd_setup(void *mmc_host, int en)
static int db1100_mmc1_cd_setup(void *mmc_host, int en)
{
{
	int ret = 0;
	int ret = 0, irq;

	if (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI)) == BCSR_WHOAMI_DB1100)
		irq = AU1100_GPIO20_INT;
	else
		irq = AU1100_GPIO15_INT;	/* PB1100 SD1 CD# */


	if (en) {
	if (en) {
		irq_set_irq_type(AU1100_GPIO20_INT, IRQ_TYPE_EDGE_BOTH);
		irq_set_irq_type(irq, IRQ_TYPE_EDGE_BOTH);
		ret = request_irq(AU1100_GPIO20_INT, db1100_mmc_cd, 0,
		ret = request_irq(irq, db1100_mmc_cd, 0,
				  "sd1_cd", mmc_host);
				  "sd1_cd", mmc_host);
	} else
	} else
		free_irq(AU1100_GPIO20_INT, mmc_host);
		free_irq(irq, mmc_host);
	return ret;
	return ret;
}
}


@@ -236,11 +253,18 @@ static int db1100_mmc_card_inserted(void *mmc_host)


static void db1100_mmc_set_power(void *mmc_host, int state)
static void db1100_mmc_set_power(void *mmc_host, int state)
{
{
	int bit;

	if (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI)) == BCSR_WHOAMI_DB1100)
		bit = BCSR_BOARD_SD0PWR;
	else
		bit = BCSR_BOARD_PB1100_SD0PWR;

	if (state) {
	if (state) {
		bcsr_mod(BCSR_BOARD, 0, BCSR_BOARD_SD0PWR);
		bcsr_mod(BCSR_BOARD, 0, bit);
		msleep(400);	/* stabilization time */
		msleep(400);	/* stabilization time */
	} else
	} else
		bcsr_mod(BCSR_BOARD, BCSR_BOARD_SD0PWR, 0);
		bcsr_mod(BCSR_BOARD, bit, 0);
}
}


static void db1100_mmcled_set(struct led_classdev *led, enum led_brightness b)
static void db1100_mmcled_set(struct led_classdev *led, enum led_brightness b)
@@ -267,11 +291,18 @@ static int db1100_mmc1_card_inserted(void *mmc_host)


static void db1100_mmc1_set_power(void *mmc_host, int state)
static void db1100_mmc1_set_power(void *mmc_host, int state)
{
{
	int bit;

	if (BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI)) == BCSR_WHOAMI_DB1100)
		bit = BCSR_BOARD_SD1PWR;
	else
		bit = BCSR_BOARD_PB1100_SD1PWR;

	if (state) {
	if (state) {
		bcsr_mod(BCSR_BOARD, 0, BCSR_BOARD_SD1PWR);
		bcsr_mod(BCSR_BOARD, 0, bit);
		msleep(400);	/* stabilization time */
		msleep(400);	/* stabilization time */
	} else
	} else
		bcsr_mod(BCSR_BOARD, BCSR_BOARD_SD1PWR, 0);
		bcsr_mod(BCSR_BOARD, bit, 0);
}
}


static void db1100_mmc1led_set(struct led_classdev *led, enum led_brightness b)
static void db1100_mmc1led_set(struct led_classdev *led, enum led_brightness b)
@@ -480,13 +511,12 @@ static struct platform_device *db1100_devs[] = {
	&db1100_mmc0_dev,
	&db1100_mmc0_dev,
	&db1100_mmc1_dev,
	&db1100_mmc1_dev,
	&db1000_irda_dev,
	&db1000_irda_dev,
	&db1100_spi_dev,
};
};


static int __init db1000_dev_init(void)
static int __init db1000_dev_init(void)
{
{
	int board = BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI));
	int board = BCSR_WHOAMI_BOARD(bcsr_read(BCSR_WHOAMI));
	int c0, c1, d0, d1, s0, s1;
	int c0, c1, d0, d1, s0, s1, flashsize = 32,  twosocks = 1;
	unsigned long pfc;
	unsigned long pfc;


	if (board == BCSR_WHOAMI_DB1500) {
	if (board == BCSR_WHOAMI_DB1500) {
@@ -522,6 +552,7 @@ static int __init db1000_dev_init(void)
					ARRAY_SIZE(db1100_spi_info));
					ARRAY_SIZE(db1100_spi_info));


		platform_add_devices(db1100_devs, ARRAY_SIZE(db1100_devs));
		platform_add_devices(db1100_devs, ARRAY_SIZE(db1100_devs));
		platform_device_register(&db1100_spi_dev);
	} else if (board == BCSR_WHOAMI_DB1000) {
	} else if (board == BCSR_WHOAMI_DB1000) {
		c0 = AU1000_GPIO2_INT;
		c0 = AU1000_GPIO2_INT;
		c1 = AU1000_GPIO5_INT;
		c1 = AU1000_GPIO5_INT;
@@ -530,15 +561,42 @@ static int __init db1000_dev_init(void)
		s0 = AU1000_GPIO1_INT;
		s0 = AU1000_GPIO1_INT;
		s1 = AU1000_GPIO4_INT;
		s1 = AU1000_GPIO4_INT;
		platform_add_devices(db1000_devs, ARRAY_SIZE(db1000_devs));
		platform_add_devices(db1000_devs, ARRAY_SIZE(db1000_devs));
	} else if ((board == BCSR_WHOAMI_PB1500) ||
		   (board == BCSR_WHOAMI_PB1500R2)) {
		c0 = AU1500_GPIO203_INT;
		d0 = AU1500_GPIO201_INT;
		s0 = AU1500_GPIO202_INT;
		twosocks = 0;
		flashsize = 64;
		/* RTC and daughtercard irqs */
		irq_set_irq_type(AU1500_GPIO204_INT, IRQ_TYPE_LEVEL_LOW);
		irq_set_irq_type(AU1500_GPIO205_INT, IRQ_TYPE_LEVEL_LOW);
		/* EPSON S1D13806 0x1b000000
		 * SRAM 1MB/2MB   0x1a000000
		 * DS1693 RTC	  0x0c000000
		 */
	} else if (board == BCSR_WHOAMI_PB1100) {
		c0 = AU1100_GPIO11_INT;
		d0 = AU1100_GPIO9_INT;
		s0 = AU1100_GPIO10_INT;
		twosocks = 0;
		flashsize = 64;
		/* pendown, rtc, daughtercard irqs */
		irq_set_irq_type(AU1100_GPIO8_INT, IRQ_TYPE_LEVEL_LOW);
		irq_set_irq_type(AU1100_GPIO12_INT, IRQ_TYPE_LEVEL_LOW);
		irq_set_irq_type(AU1100_GPIO13_INT, IRQ_TYPE_LEVEL_LOW);
		/* EPSON S1D13806 0x1b000000
		 * SRAM 1MB/2MB   0x1a000000
		 * DiskOnChip	  0x0d000000
		 * DS1693 RTC	  0x0c000000
		 */
		platform_add_devices(db1100_devs, ARRAY_SIZE(db1100_devs));
	} else
	} else
		return 0; /* unknown board, no further dev setup to do */
		return 0; /* unknown board, no further dev setup to do */


	irq_set_irq_type(d0, IRQ_TYPE_EDGE_BOTH);
	irq_set_irq_type(d0, IRQ_TYPE_EDGE_BOTH);
	irq_set_irq_type(d1, IRQ_TYPE_EDGE_BOTH);
	irq_set_irq_type(c0, IRQ_TYPE_LEVEL_LOW);
	irq_set_irq_type(c0, IRQ_TYPE_LEVEL_LOW);
	irq_set_irq_type(c1, IRQ_TYPE_LEVEL_LOW);
	irq_set_irq_type(s0, IRQ_TYPE_LEVEL_LOW);
	irq_set_irq_type(s0, IRQ_TYPE_LEVEL_LOW);
	irq_set_irq_type(s1, IRQ_TYPE_LEVEL_LOW);


	db1x_register_pcmcia_socket(
	db1x_register_pcmcia_socket(
		AU1000_PCMCIA_ATTR_PHYS_ADDR,
		AU1000_PCMCIA_ATTR_PHYS_ADDR,
@@ -549,6 +607,11 @@ static int __init db1000_dev_init(void)
		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
		c0, d0,	/*s0*/0, 0, 0);
		c0, d0,	/*s0*/0, 0, 0);


	if (twosocks) {
		irq_set_irq_type(d1, IRQ_TYPE_EDGE_BOTH);
		irq_set_irq_type(c1, IRQ_TYPE_LEVEL_LOW);
		irq_set_irq_type(s1, IRQ_TYPE_LEVEL_LOW);

		db1x_register_pcmcia_socket(
		db1x_register_pcmcia_socket(
			AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004000000,
			AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004000000,
			AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004400000 - 1,
			AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x004400000 - 1,
@@ -557,9 +620,10 @@ static int __init db1000_dev_init(void)
			AU1000_PCMCIA_IO_PHYS_ADDR   + 0x004000000,
			AU1000_PCMCIA_IO_PHYS_ADDR   + 0x004000000,
			AU1000_PCMCIA_IO_PHYS_ADDR   + 0x004010000 - 1,
			AU1000_PCMCIA_IO_PHYS_ADDR   + 0x004010000 - 1,
			c1, d1,	/*s1*/0, 0, 1);
			c1, d1,	/*s1*/0, 0, 1);
	}


	platform_add_devices(db1x00_devs, ARRAY_SIZE(db1x00_devs));
	platform_add_devices(db1x00_devs, ARRAY_SIZE(db1x00_devs));
	db1x_register_norflash(32 << 20, 4 /* 32bit */, F_SWAPPED);
	db1x_register_norflash(flashsize << 20, 4 /* 32bit */, F_SWAPPED);
	return 0;
	return 0;
}
}
device_initcall(db1000_dev_init);
device_initcall(db1000_dev_init);
+0 −167
Original line number Original line Diff line number Diff line
/*
 * Pb1100 board platform device registration
 *
 * Copyright (C) 2009 Manuel Lauss
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/dma-mapping.h>
#include <linux/platform_device.h>
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-db1x00/bcsr.h>
#include <prom.h>
#include "platform.h"

const char *get_system_type(void)
{
	return "PB1100";
}

void __init board_setup(void)
{
	volatile void __iomem *base = (volatile void __iomem *)0xac000000UL;

	bcsr_init(DB1000_BCSR_PHYS_ADDR,
		  DB1000_BCSR_PHYS_ADDR + DB1000_BCSR_HEXLED_OFS);

	/* Set AUX clock to 12 MHz * 8 = 96 MHz */
	au_writel(8, SYS_AUXPLL);
	alchemy_gpio1_input_enable();
	udelay(100);

#if IS_ENABLED(CONFIG_USB_OHCI_HCD)
	{
		u32 pin_func, sys_freqctrl, sys_clksrc;

		/* Configure pins GPIO[14:9] as GPIO */
		pin_func = au_readl(SYS_PINFUNC) & ~SYS_PF_UR3;

		/* Zero and disable FREQ2 */
		sys_freqctrl = au_readl(SYS_FREQCTRL0);
		sys_freqctrl &= ~0xFFF00000;
		au_writel(sys_freqctrl, SYS_FREQCTRL0);

		/* Zero and disable USBH/USBD/IrDA clock */
		sys_clksrc = au_readl(SYS_CLKSRC);
		sys_clksrc &= ~(SYS_CS_CIR | SYS_CS_DIR | SYS_CS_MIR_MASK);
		au_writel(sys_clksrc, SYS_CLKSRC);

		sys_freqctrl = au_readl(SYS_FREQCTRL0);
		sys_freqctrl &= ~0xFFF00000;

		sys_clksrc = au_readl(SYS_CLKSRC);
		sys_clksrc &= ~(SYS_CS_CIR | SYS_CS_DIR | SYS_CS_MIR_MASK);

		/* FREQ2 = aux / 2 = 48 MHz */
		sys_freqctrl |= (0 << SYS_FC_FRDIV2_BIT) |
				SYS_FC_FE2 | SYS_FC_FS2;
		au_writel(sys_freqctrl, SYS_FREQCTRL0);

		/*
		 * Route 48 MHz FREQ2 into USBH/USBD/IrDA
		 */
		sys_clksrc |= SYS_CS_MUX_FQ2 << SYS_CS_MIR_BIT;
		au_writel(sys_clksrc, SYS_CLKSRC);

		/* Setup the static bus controller */
		au_writel(0x00000002, MEM_STCFG3);  /* type = PCMCIA */
		au_writel(0x280E3D07, MEM_STTIME3); /* 250ns cycle time */
		au_writel(0x10000000, MEM_STADDR3); /* any PCMCIA select */

		/*
		 * Get USB Functionality pin state (device vs host drive pins).
		 */
		pin_func = au_readl(SYS_PINFUNC) & ~SYS_PF_USB;
		/* 2nd USB port is USB host. */
		pin_func |= SYS_PF_USB;
		au_writel(pin_func, SYS_PINFUNC);
	}
#endif /* IS_ENABLED(CONFIG_USB_OHCI_HCD) */

	/* Enable sys bus clock divider when IDLE state or no bus activity. */
	au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL);

	/* Enable the RTC if not already enabled. */
	if (!(readb(base + 0x28) & 0x20)) {
		writeb(readb(base + 0x28) | 0x20, base + 0x28);
		au_sync();
	}
	/* Put the clock in BCD mode. */
	if (readb(base + 0x2C) & 0x4) { /* reg B */
		writeb(readb(base + 0x2c) & ~0x4, base + 0x2c);
		au_sync();
	}
}

/******************************************************************************/

static struct resource au1100_lcd_resources[] = {
	[0] = {
		.start	= AU1100_LCD_PHYS_ADDR,
		.end	= AU1100_LCD_PHYS_ADDR + 0x800 - 1,
		.flags	= IORESOURCE_MEM,
	},
	[1] = {
		.start	= AU1100_LCD_INT,
		.end	= AU1100_LCD_INT,
		.flags	= IORESOURCE_IRQ,
	}
};

static u64 au1100_lcd_dmamask = DMA_BIT_MASK(32);

static struct platform_device au1100_lcd_device = {
	.name		= "au1100-lcd",
	.id		= 0,
	.dev = {
		.dma_mask		= &au1100_lcd_dmamask,
		.coherent_dma_mask	= DMA_BIT_MASK(32),
	},
	.num_resources	= ARRAY_SIZE(au1100_lcd_resources),
	.resource	= au1100_lcd_resources,
};

static int __init pb1100_dev_init(void)
{
	int swapped;

	irq_set_irq_type(AU1100_GPIO9_INT, IRQF_TRIGGER_LOW); /* PCCD# */
	irq_set_irq_type(AU1100_GPIO10_INT, IRQF_TRIGGER_LOW); /* PCSTSCHG# */
	irq_set_irq_type(AU1100_GPIO11_INT, IRQF_TRIGGER_LOW); /* PCCard# */
	irq_set_irq_type(AU1100_GPIO13_INT, IRQF_TRIGGER_LOW); /* DC_IRQ# */

	/* PCMCIA. single socket, identical to Pb1500 */
	db1x_register_pcmcia_socket(
		AU1000_PCMCIA_ATTR_PHYS_ADDR,
		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
		AU1000_PCMCIA_MEM_PHYS_ADDR,
		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x000400000 - 1,
		AU1000_PCMCIA_IO_PHYS_ADDR,
		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
		AU1100_GPIO11_INT, AU1100_GPIO9_INT,	 /* card / insert */
		/*AU1100_GPIO10_INT*/0, 0, 0); /* stschg / eject / id */

	swapped = bcsr_read(BCSR_STATUS) &  BCSR_STATUS_DB1000_SWAPBOOT;
	db1x_register_norflash(64 * 1024 * 1024, 4, swapped);
	platform_device_register(&au1100_lcd_device);

	return 0;
}
device_initcall(pb1100_dev_init);
+0 −198
Original line number Original line Diff line number Diff line
/*
 * Pb1500 board support.
 *
 * Copyright (C) 2009 Manuel Lauss
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/gpio.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
#include <asm/mach-au1x00/au1000.h>
#include <asm/mach-db1x00/bcsr.h>
#include <prom.h>
#include "platform.h"

const char *get_system_type(void)
{
	return "PB1500";
}

void __init board_setup(void)
{
	u32 pin_func;
	u32 sys_freqctrl, sys_clksrc;

	bcsr_init(DB1000_BCSR_PHYS_ADDR,
		  DB1000_BCSR_PHYS_ADDR + DB1000_BCSR_HEXLED_OFS);

	sys_clksrc = sys_freqctrl = pin_func = 0;
	/* Set AUX clock to 12 MHz * 8 = 96 MHz */
	au_writel(8, SYS_AUXPLL);
	alchemy_gpio1_input_enable();
	udelay(100);

	/* GPIO201 is input for PCMCIA card detect */
	/* GPIO203 is input for PCMCIA interrupt request */
	alchemy_gpio_direction_input(201);
	alchemy_gpio_direction_input(203);

#if IS_ENABLED(CONFIG_USB_OHCI_HCD)

	/* Zero and disable FREQ2 */
	sys_freqctrl = au_readl(SYS_FREQCTRL0);
	sys_freqctrl &= ~0xFFF00000;
	au_writel(sys_freqctrl, SYS_FREQCTRL0);

	/* zero and disable USBH/USBD clocks */
	sys_clksrc = au_readl(SYS_CLKSRC);
	sys_clksrc &= ~(SYS_CS_CUD | SYS_CS_DUD | SYS_CS_MUD_MASK |
			SYS_CS_CUH | SYS_CS_DUH | SYS_CS_MUH_MASK);
	au_writel(sys_clksrc, SYS_CLKSRC);

	sys_freqctrl = au_readl(SYS_FREQCTRL0);
	sys_freqctrl &= ~0xFFF00000;

	sys_clksrc = au_readl(SYS_CLKSRC);
	sys_clksrc &= ~(SYS_CS_CUD | SYS_CS_DUD | SYS_CS_MUD_MASK |
			SYS_CS_CUH | SYS_CS_DUH | SYS_CS_MUH_MASK);

	/* FREQ2 = aux/2 = 48 MHz */
	sys_freqctrl |= (0 << SYS_FC_FRDIV2_BIT) | SYS_FC_FE2 | SYS_FC_FS2;
	au_writel(sys_freqctrl, SYS_FREQCTRL0);

	/*
	 * Route 48MHz FREQ2 into USB Host and/or Device
	 */
	sys_clksrc |= SYS_CS_MUX_FQ2 << SYS_CS_MUH_BIT;
	au_writel(sys_clksrc, SYS_CLKSRC);

	pin_func = au_readl(SYS_PINFUNC) & ~SYS_PF_USB;
	/* 2nd USB port is USB host */
	pin_func |= SYS_PF_USB;
	au_writel(pin_func, SYS_PINFUNC);
#endif /* IS_ENABLED(CONFIG_USB_OHCI_HCD) */

#ifdef CONFIG_PCI
	{
		void __iomem *base =
				(void __iomem *)KSEG1ADDR(AU1500_PCI_PHYS_ADDR);
		/* Setup PCI bus controller */
		__raw_writel(0x00003fff, base + PCI_REG_CMEM);
		__raw_writel(0xf0000000, base + PCI_REG_MWMASK_DEV);
		__raw_writel(0, base + PCI_REG_MWBASE_REV_CCL);
		__raw_writel(0x02a00356, base + PCI_REG_STATCMD);
		__raw_writel(0x00003c04, base + PCI_REG_PARAM);
		__raw_writel(0x00000008, base + PCI_REG_MBAR);
		wmb();
	}
#endif

	/* Enable sys bus clock divider when IDLE state or no bus activity. */
	au_writel(au_readl(SYS_POWERCTRL) | (0x3 << 5), SYS_POWERCTRL);

	/* Enable the RTC if not already enabled */
	if (!(au_readl(0xac000028) & 0x20)) {
		printk(KERN_INFO "enabling clock ...\n");
		au_writel((au_readl(0xac000028) | 0x20), 0xac000028);
	}
	/* Put the clock in BCD mode */
	if (au_readl(0xac00002c) & 0x4) { /* reg B */
		au_writel(au_readl(0xac00002c) & ~0x4, 0xac00002c);
		au_sync();
	}
}

/******************************************************************************/

static int pb1500_map_pci_irq(const struct pci_dev *d, u8 slot, u8 pin)
{
	if ((slot < 12) || (slot > 13) || pin == 0)
		return -1;
	if (slot == 12)
		return (pin == 1) ? AU1500_PCI_INTA : 0xff;
	if (slot == 13) {
		switch (pin) {
		case 1: return AU1500_PCI_INTA;
		case 2: return AU1500_PCI_INTB;
		case 3: return AU1500_PCI_INTC;
		case 4: return AU1500_PCI_INTD;
		}
	}
	return -1;
}

static struct resource alchemy_pci_host_res[] = {
	[0] = {
		.start	= AU1500_PCI_PHYS_ADDR,
		.end	= AU1500_PCI_PHYS_ADDR + 0xfff,
		.flags	= IORESOURCE_MEM,
	},
};

static struct alchemy_pci_platdata pb1500_pci_pd = {
	.board_map_irq	= pb1500_map_pci_irq,
	.pci_cfg_set	= PCI_CONFIG_AEN | PCI_CONFIG_R2H | PCI_CONFIG_R1H |
			  PCI_CONFIG_CH |
#if defined(__MIPSEB__)
			  PCI_CONFIG_SIC_HWA_DAT | PCI_CONFIG_SM,
#else
			  0,
#endif
};

static struct platform_device pb1500_pci_host = {
	.dev.platform_data = &pb1500_pci_pd,
	.name		= "alchemy-pci",
	.id		= 0,
	.num_resources	= ARRAY_SIZE(alchemy_pci_host_res),
	.resource	= alchemy_pci_host_res,
};

static int __init pb1500_dev_init(void)
{
	int swapped;

	irq_set_irq_type(AU1500_GPIO9_INT,   IRQF_TRIGGER_LOW);   /* CD0# */
	irq_set_irq_type(AU1500_GPIO10_INT,  IRQF_TRIGGER_LOW);  /* CARD0 */
	irq_set_irq_type(AU1500_GPIO11_INT,  IRQF_TRIGGER_LOW);  /* STSCHG0# */
	irq_set_irq_type(AU1500_GPIO204_INT, IRQF_TRIGGER_HIGH);
	irq_set_irq_type(AU1500_GPIO201_INT, IRQF_TRIGGER_LOW);
	irq_set_irq_type(AU1500_GPIO202_INT, IRQF_TRIGGER_LOW);
	irq_set_irq_type(AU1500_GPIO203_INT, IRQF_TRIGGER_LOW);
	irq_set_irq_type(AU1500_GPIO205_INT, IRQF_TRIGGER_LOW);

	/* PCMCIA. single socket, identical to Pb1100 */
	db1x_register_pcmcia_socket(
		AU1000_PCMCIA_ATTR_PHYS_ADDR,
		AU1000_PCMCIA_ATTR_PHYS_ADDR + 0x000400000 - 1,
		AU1000_PCMCIA_MEM_PHYS_ADDR,
		AU1000_PCMCIA_MEM_PHYS_ADDR  + 0x000400000 - 1,
		AU1000_PCMCIA_IO_PHYS_ADDR,
		AU1000_PCMCIA_IO_PHYS_ADDR   + 0x000010000 - 1,
		AU1500_GPIO11_INT, AU1500_GPIO9_INT,	 /* card / insert */
		/*AU1500_GPIO10_INT*/0, 0, 0); /* stschg / eject / id */

	swapped = bcsr_read(BCSR_STATUS) &  BCSR_STATUS_DB1000_SWAPBOOT;
	db1x_register_norflash(64 * 1024 * 1024, 4, swapped);
	platform_device_register(&pb1500_pci_host);

	return 0;
}
arch_initcall(pb1500_dev_init);
Loading