Commit 809f36c6 authored by Manuel Lauss's avatar Manuel Lauss Committed by Ralf Baechle

MIPS: Alchemy: Au1300 SoC support

Add basic support for the Au1300 variant(s):
- New GPIO/Interrupt controller
- DBDMA ids
- USB setup
- MMC support
- enable various PSC drivers
- detection code.
Signed-off-by: default avatarManuel Lauss <manuel.lauss@googlemail.com>
To: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/2866/Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent fb469f08
...@@ -2,6 +2,10 @@ ...@@ -2,6 +2,10 @@
config ALCHEMY_GPIOINT_AU1000 config ALCHEMY_GPIOINT_AU1000
bool bool
# au1300-style GPIO/INT controller
config ALCHEMY_GPIOINT_AU1300
bool
# select this in your board config if you don't want to use the gpio # select this in your board config if you don't want to use the gpio
# namespace as documented in the manuals. In this case however you need # namespace as documented in the manuals. In this case however you need
# to create the necessary gpio_* functions in your board code/headers! # to create the necessary gpio_* functions in your board code/headers!
......
...@@ -6,9 +6,10 @@ ...@@ -6,9 +6,10 @@
# #
obj-y += prom.o time.o clocks.o platform.o power.o setup.o \ obj-y += prom.o time.o clocks.o platform.o power.o setup.o \
sleeper.o dma.o dbdma.o sleeper.o dma.o dbdma.o vss.o
obj-$(CONFIG_ALCHEMY_GPIOINT_AU1000) += irq.o obj-$(CONFIG_ALCHEMY_GPIOINT_AU1000) += irq.o
obj-$(CONFIG_ALCHEMY_GPIOINT_AU1300) += gpioint.o
# optional gpiolib support # optional gpiolib support
ifeq ($(CONFIG_ALCHEMY_GPIO_INDIRECT),) ifeq ($(CONFIG_ALCHEMY_GPIO_INDIRECT),)
......
...@@ -148,6 +148,50 @@ static dbdev_tab_t au1200_dbdev_tab[] __initdata = { ...@@ -148,6 +148,50 @@ static dbdev_tab_t au1200_dbdev_tab[] __initdata = {
{ DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 }, { DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
}; };
static dbdev_tab_t au1300_dbdev_tab[] __initdata = {
{ AU1300_DSCR_CMD0_UART0_TX, DEV_FLAGS_OUT, 0, 8, 0x10100004, 0, 0 },
{ AU1300_DSCR_CMD0_UART0_RX, DEV_FLAGS_IN, 0, 8, 0x10100000, 0, 0 },
{ AU1300_DSCR_CMD0_UART1_TX, DEV_FLAGS_OUT, 0, 8, 0x10101004, 0, 0 },
{ AU1300_DSCR_CMD0_UART1_RX, DEV_FLAGS_IN, 0, 8, 0x10101000, 0, 0 },
{ AU1300_DSCR_CMD0_UART2_TX, DEV_FLAGS_OUT, 0, 8, 0x10102004, 0, 0 },
{ AU1300_DSCR_CMD0_UART2_RX, DEV_FLAGS_IN, 0, 8, 0x10102000, 0, 0 },
{ AU1300_DSCR_CMD0_UART3_TX, DEV_FLAGS_OUT, 0, 8, 0x10103004, 0, 0 },
{ AU1300_DSCR_CMD0_UART3_RX, DEV_FLAGS_IN, 0, 8, 0x10103000, 0, 0 },
{ AU1300_DSCR_CMD0_SDMS_TX0, DEV_FLAGS_OUT, 4, 8, 0x10600000, 0, 0 },
{ AU1300_DSCR_CMD0_SDMS_RX0, DEV_FLAGS_IN, 4, 8, 0x10600004, 0, 0 },
{ AU1300_DSCR_CMD0_SDMS_TX1, DEV_FLAGS_OUT, 8, 8, 0x10601000, 0, 0 },
{ AU1300_DSCR_CMD0_SDMS_RX1, DEV_FLAGS_IN, 8, 8, 0x10601004, 0, 0 },
{ AU1300_DSCR_CMD0_AES_RX, DEV_FLAGS_IN , 4, 32, 0x10300008, 0, 0 },
{ AU1300_DSCR_CMD0_AES_TX, DEV_FLAGS_OUT, 4, 32, 0x10300004, 0, 0 },
{ AU1300_DSCR_CMD0_PSC0_TX, DEV_FLAGS_OUT, 0, 16, 0x10a0001c, 0, 0 },
{ AU1300_DSCR_CMD0_PSC0_RX, DEV_FLAGS_IN, 0, 16, 0x10a0001c, 0, 0 },
{ AU1300_DSCR_CMD0_PSC1_TX, DEV_FLAGS_OUT, 0, 16, 0x10a0101c, 0, 0 },
{ AU1300_DSCR_CMD0_PSC1_RX, DEV_FLAGS_IN, 0, 16, 0x10a0101c, 0, 0 },
{ AU1300_DSCR_CMD0_PSC2_TX, DEV_FLAGS_OUT, 0, 16, 0x10a0201c, 0, 0 },
{ AU1300_DSCR_CMD0_PSC2_RX, DEV_FLAGS_IN, 0, 16, 0x10a0201c, 0, 0 },
{ AU1300_DSCR_CMD0_PSC3_TX, DEV_FLAGS_OUT, 0, 16, 0x10a0301c, 0, 0 },
{ AU1300_DSCR_CMD0_PSC3_RX, DEV_FLAGS_IN, 0, 16, 0x10a0301c, 0, 0 },
{ AU1300_DSCR_CMD0_LCD, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
{ AU1300_DSCR_CMD0_NAND_FLASH, DEV_FLAGS_IN, 0, 0, 0x00000000, 0, 0 },
{ AU1300_DSCR_CMD0_SDMS_TX2, DEV_FLAGS_OUT, 4, 8, 0x10602000, 0, 0 },
{ AU1300_DSCR_CMD0_SDMS_RX2, DEV_FLAGS_IN, 4, 8, 0x10602004, 0, 0 },
{ AU1300_DSCR_CMD0_CIM_SYNC, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
{ AU1300_DSCR_CMD0_UDMA, DEV_FLAGS_ANYUSE, 0, 32, 0x14001810, 0, 0 },
{ AU1300_DSCR_CMD0_DMA_REQ0, 0, 0, 0, 0x00000000, 0, 0 },
{ AU1300_DSCR_CMD0_DMA_REQ1, 0, 0, 0, 0x00000000, 0, 0 },
{ DSCR_CMD0_THROTTLE, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
{ DSCR_CMD0_ALWAYS, DEV_FLAGS_ANYUSE, 0, 0, 0x00000000, 0, 0 },
};
/* 32 predefined plus 32 custom */ /* 32 predefined plus 32 custom */
#define DBDEV_TAB_SIZE 64 #define DBDEV_TAB_SIZE 64
...@@ -1038,6 +1082,8 @@ static int __init alchemy_dbdma_init(void) ...@@ -1038,6 +1082,8 @@ static int __init alchemy_dbdma_init(void)
return dbdma_setup(AU1550_DDMA_INT, au1550_dbdev_tab); return dbdma_setup(AU1550_DDMA_INT, au1550_dbdev_tab);
case ALCHEMY_CPU_AU1200: case ALCHEMY_CPU_AU1200:
return dbdma_setup(AU1200_DDMA_INT, au1200_dbdev_tab); return dbdma_setup(AU1200_DDMA_INT, au1200_dbdev_tab);
case ALCHEMY_CPU_AU1300:
return dbdma_setup(AU1300_DDMA_INT, au1300_dbdev_tab);
} }
return 0; return 0;
} }
......
This diff is collapsed.
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
* CONFIG_ALCHEMY_GPIO_INDIRECT=n, otherwise compilation will fail! * CONFIG_ALCHEMY_GPIO_INDIRECT=n, otherwise compilation will fail!
* au1000 SoC have only one GPIO block : GPIO1 * au1000 SoC have only one GPIO block : GPIO1
* Au1100, Au15x0, Au12x0 have a second one : GPIO2 * Au1100, Au15x0, Au12x0 have a second one : GPIO2
* Au1300 is totally different: 1 block with up to 128 GPIOs
*/ */
#include <linux/init.h> #include <linux/init.h>
...@@ -35,6 +36,7 @@ ...@@ -35,6 +36,7 @@
#include <linux/types.h> #include <linux/types.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <asm/mach-au1x00/gpio-au1000.h> #include <asm/mach-au1x00/gpio-au1000.h>
#include <asm/mach-au1x00/gpio-au1300.h>
static int gpio2_get(struct gpio_chip *chip, unsigned offset) static int gpio2_get(struct gpio_chip *chip, unsigned offset)
{ {
...@@ -115,6 +117,43 @@ struct gpio_chip alchemy_gpio_chip[] = { ...@@ -115,6 +117,43 @@ struct gpio_chip alchemy_gpio_chip[] = {
}, },
}; };
static int alchemy_gpic_get(struct gpio_chip *chip, unsigned int off)
{
return au1300_gpio_get_value(off + AU1300_GPIO_BASE);
}
static void alchemy_gpic_set(struct gpio_chip *chip, unsigned int off, int v)
{
au1300_gpio_set_value(off + AU1300_GPIO_BASE, v);
}
static int alchemy_gpic_dir_input(struct gpio_chip *chip, unsigned int off)
{
return au1300_gpio_direction_input(off + AU1300_GPIO_BASE);
}
static int alchemy_gpic_dir_output(struct gpio_chip *chip, unsigned int off,
int v)
{
return au1300_gpio_direction_output(off + AU1300_GPIO_BASE, v);
}
static int alchemy_gpic_gpio_to_irq(struct gpio_chip *chip, unsigned int off)
{
return au1300_gpio_to_irq(off + AU1300_GPIO_BASE);
}
static struct gpio_chip au1300_gpiochip = {
.label = "alchemy-gpic",
.direction_input = alchemy_gpic_dir_input,
.direction_output = alchemy_gpic_dir_output,
.get = alchemy_gpic_get,
.set = alchemy_gpic_set,
.to_irq = alchemy_gpic_gpio_to_irq,
.base = AU1300_GPIO_BASE,
.ngpio = AU1300_GPIO_NUM,
};
static int __init alchemy_gpiochip_init(void) static int __init alchemy_gpiochip_init(void)
{ {
int ret = 0; int ret = 0;
...@@ -127,6 +166,9 @@ static int __init alchemy_gpiochip_init(void) ...@@ -127,6 +166,9 @@ static int __init alchemy_gpiochip_init(void)
ret = gpiochip_add(&alchemy_gpio_chip[0]); ret = gpiochip_add(&alchemy_gpio_chip[0]);
ret |= gpiochip_add(&alchemy_gpio_chip[1]); ret |= gpiochip_add(&alchemy_gpio_chip[1]);
break; break;
case ALCHEMY_CPU_AU1300:
ret = gpiochip_add(&au1300_gpiochip);
break;
} }
return ret; return ret;
} }
......
...@@ -82,6 +82,12 @@ static struct plat_serial8250_port au1x00_uart_data[][4] __initdata = { ...@@ -82,6 +82,12 @@ static struct plat_serial8250_port au1x00_uart_data[][4] __initdata = {
PORT(AU1000_UART0_PHYS_ADDR, AU1200_UART0_INT), PORT(AU1000_UART0_PHYS_ADDR, AU1200_UART0_INT),
PORT(AU1000_UART1_PHYS_ADDR, AU1200_UART1_INT), PORT(AU1000_UART1_PHYS_ADDR, AU1200_UART1_INT),
}, },
[ALCHEMY_CPU_AU1300] = {
PORT(AU1300_UART0_PHYS_ADDR, AU1300_UART0_INT),
PORT(AU1300_UART1_PHYS_ADDR, AU1300_UART1_INT),
PORT(AU1300_UART2_PHYS_ADDR, AU1300_UART2_INT),
PORT(AU1300_UART3_PHYS_ADDR, AU1300_UART3_INT),
},
}; };
static struct platform_device au1xx0_uart_device = { static struct platform_device au1xx0_uart_device = {
...@@ -122,10 +128,12 @@ static unsigned long alchemy_ohci_data[][2] __initdata = { ...@@ -122,10 +128,12 @@ static unsigned long alchemy_ohci_data[][2] __initdata = {
[ALCHEMY_CPU_AU1100] = { AU1000_USB_OHCI_PHYS_ADDR, AU1100_USB_HOST_INT }, [ALCHEMY_CPU_AU1100] = { AU1000_USB_OHCI_PHYS_ADDR, AU1100_USB_HOST_INT },
[ALCHEMY_CPU_AU1550] = { AU1550_USB_OHCI_PHYS_ADDR, AU1550_USB_HOST_INT }, [ALCHEMY_CPU_AU1550] = { AU1550_USB_OHCI_PHYS_ADDR, AU1550_USB_HOST_INT },
[ALCHEMY_CPU_AU1200] = { AU1200_USB_OHCI_PHYS_ADDR, AU1200_USB_INT }, [ALCHEMY_CPU_AU1200] = { AU1200_USB_OHCI_PHYS_ADDR, AU1200_USB_INT },
[ALCHEMY_CPU_AU1300] = { AU1300_USB_OHCI0_PHYS_ADDR, AU1300_USB_INT },
}; };
static unsigned long alchemy_ehci_data[][2] __initdata = { static unsigned long alchemy_ehci_data[][2] __initdata = {
[ALCHEMY_CPU_AU1200] = { AU1200_USB_EHCI_PHYS_ADDR, AU1200_USB_INT }, [ALCHEMY_CPU_AU1200] = { AU1200_USB_EHCI_PHYS_ADDR, AU1200_USB_INT },
[ALCHEMY_CPU_AU1300] = { AU1300_USB_EHCI_PHYS_ADDR, AU1300_USB_INT },
}; };
static int __init _new_usbres(struct resource **r, struct platform_device **d) static int __init _new_usbres(struct resource **r, struct platform_device **d)
...@@ -169,8 +177,8 @@ static void __init alchemy_setup_usb(int ctype) ...@@ -169,8 +177,8 @@ static void __init alchemy_setup_usb(int ctype)
printk(KERN_INFO "Alchemy USB: cannot add OHCI0\n"); printk(KERN_INFO "Alchemy USB: cannot add OHCI0\n");
/* setup EHCI0: Au1200 */ /* setup EHCI0: Au1200/Au1300 */
if (ctype == ALCHEMY_CPU_AU1200) { if ((ctype == ALCHEMY_CPU_AU1200) || (ctype == ALCHEMY_CPU_AU1300)) {
if (_new_usbres(&res, &pdev)) if (_new_usbres(&res, &pdev))
return; return;
...@@ -187,6 +195,25 @@ static void __init alchemy_setup_usb(int ctype) ...@@ -187,6 +195,25 @@ static void __init alchemy_setup_usb(int ctype)
if (platform_device_register(pdev)) if (platform_device_register(pdev))
printk(KERN_INFO "Alchemy USB: cannot add EHCI0\n"); printk(KERN_INFO "Alchemy USB: cannot add EHCI0\n");
} }
/* Au1300: OHCI1 */
if (ctype == ALCHEMY_CPU_AU1300) {
if (_new_usbres(&res, &pdev))
return;
res[0].start = AU1300_USB_OHCI1_PHYS_ADDR;
res[0].end = res[0].start + 0x100 - 1;
res[0].flags = IORESOURCE_MEM;
res[1].start = AU1300_USB_INT;
res[1].end = res[1].start;
res[1].flags = IORESOURCE_IRQ;
pdev->name = "au1xxx-ohci";
pdev->id = 1;
pdev->dev.dma_mask = &alchemy_ohci_dmamask;
if (platform_device_register(pdev))
printk(KERN_INFO "Alchemy USB: cannot add OHCI1\n");
}
} }
/* Macro to help defining the Ethernet MAC resources */ /* Macro to help defining the Ethernet MAC resources */
......
...@@ -126,6 +126,9 @@ void au_sleep(void) ...@@ -126,6 +126,9 @@ void au_sleep(void)
case ALCHEMY_CPU_AU1200: case ALCHEMY_CPU_AU1200:
alchemy_sleep_au1550(); alchemy_sleep_au1550();
break; break;
case ALCHEMY_CPU_AU1300:
alchemy_sleep_au1300();
break;
} }
restore_core_regs(); restore_core_regs();
......
...@@ -153,6 +153,79 @@ LEAF(alchemy_sleep_au1550) ...@@ -153,6 +153,79 @@ LEAF(alchemy_sleep_au1550)
END(alchemy_sleep_au1550) END(alchemy_sleep_au1550)
/* sleepcode for Au1300 memory controller type */
LEAF(alchemy_sleep_au1300)
SETUP_SLEEP
/* cache following instructions, as memory gets put to sleep */
la t0, 2f
la t1, 4f
subu t2, t1, t0
.set mips3
1: cache 0x14, 0(t0)
subu t2, t2, 32
bgez t2, 1b
addu t0, t0, 32
.set mips0
2: lui a0, 0xb400 /* mem_xxx */
/* disable all ports in mem_sdportcfga */
sw zero, 0x868(a0) /* mem_sdportcfga */
sync
/* disable ODT */
li t0, 0x03010000
sw t0, 0x08d8(a0) /* mem_sdcmd0 */
sw t0, 0x08dc(a0) /* mem_sdcmd1 */
sync
/* precharge */
li t0, 0x23000400
sw t0, 0x08dc(a0) /* mem_sdcmd1 */
sw t0, 0x08d8(a0) /* mem_sdcmd0 */
sync
/* auto refresh */
sw zero, 0x08c8(a0) /* mem_sdautoref */
sync
/* block access to the DDR */
lw t0, 0x0848(a0) /* mem_sdconfigb */
li t1, (1 << 7 | 0x3F)
or t0, t0, t1
sw t0, 0x0848(a0) /* mem_sdconfigb */
sync
/* issue the Self Refresh command */
li t0, 0x10000000
sw t0, 0x08dc(a0) /* mem_sdcmd1 */
sw t0, 0x08d8(a0) /* mem_sdcmd0 */
sync
/* wait for sdram to enter self-refresh mode */
lui t0, 0x0300
3: lw t1, 0x0850(a0) /* mem_sdstat */
and t2, t1, t0
bne t2, t0, 3b
nop
/* disable SDRAM clocks */
li t0, ~(3<<28)
lw t1, 0x0840(a0) /* mem_sdconfiga */
and t1, t1, t0 /* clear CE[1:0] */
sw t1, 0x0840(a0) /* mem_sdconfiga */
sync
DO_SLEEP
4:
END(alchemy_sleep_au1300)
/* This is where we return upon wakeup. /* This is where we return upon wakeup.
* Reload all of the registers and return. * Reload all of the registers and return.
......
...@@ -178,6 +178,7 @@ static int alchemy_m2inttab[] __initdata = { ...@@ -178,6 +178,7 @@ static int alchemy_m2inttab[] __initdata = {
AU1100_RTC_MATCH2_INT, AU1100_RTC_MATCH2_INT,
AU1550_RTC_MATCH2_INT, AU1550_RTC_MATCH2_INT,
AU1200_RTC_MATCH2_INT, AU1200_RTC_MATCH2_INT,
AU1300_RTC_MATCH2_INT,
}; };
void __init plat_time_init(void) void __init plat_time_init(void)
......
/*
* Au1300 media block power gating (VSS)
*
* This is a stop-gap solution until I have the clock framework integration
* ready. This stuff here really must be handled transparently when clocks
* for various media blocks are enabled/disabled.
*/
#include <linux/module.h>
#include <linux/spinlock.h>
#include <asm/mach-au1x00/au1000.h>
#define VSS_GATE 0x00 /* gate wait timers */
#define VSS_CLKRST 0x04 /* clock/block control */
#define VSS_FTR 0x08 /* footers */
#define VSS_ADDR(blk) (KSEG1ADDR(AU1300_VSS_PHYS_ADDR) + (blk * 0x0c))
static DEFINE_SPINLOCK(au1300_vss_lock);
/* enable a block as outlined in the databook */
static inline void __enable_block(int block)
{
void __iomem *base = (void __iomem *)VSS_ADDR(block);
__raw_writel(3, base + VSS_CLKRST); /* enable clock, assert reset */
wmb();
__raw_writel(0x01fffffe, base + VSS_GATE); /* maximum setup time */
wmb();
/* enable footers in sequence */
__raw_writel(0x01, base + VSS_FTR);
wmb();
__raw_writel(0x03, base + VSS_FTR);
wmb();
__raw_writel(0x07, base + VSS_FTR);
wmb();
__raw_writel(0x0f, base + VSS_FTR);
wmb();
__raw_writel(0x01ffffff, base + VSS_GATE); /* start FSM too */
wmb();
__raw_writel(2, base + VSS_CLKRST); /* deassert reset */
wmb();
__raw_writel(0x1f, base + VSS_FTR); /* enable isolation cells */
wmb();
}
/* disable a block as outlined in the databook */
static inline void __disable_block(int block)
{
void __iomem *base = (void __iomem *)VSS_ADDR(block);
__raw_writel(0x0f, base + VSS_FTR); /* disable isolation cells */
wmb();
__raw_writel(0, base + VSS_GATE); /* disable FSM */
wmb();
__raw_writel(3, base + VSS_CLKRST); /* assert reset */
wmb();
__raw_writel(1, base + VSS_CLKRST); /* disable clock */
wmb();
__raw_writel(0, base + VSS_FTR); /* disable all footers */
wmb();
}
void au1300_vss_block_control(int block, int enable)
{
unsigned long flags;
if (alchemy_get_cputype() != ALCHEMY_CPU_AU1300)
return;
/* only one block at a time */
spin_lock_irqsave(&au1300_vss_lock, flags);
if (enable)
__enable_block(block);
else
__disable_block(block);
spin_unlock_irqrestore(&au1300_vss_lock, flags);
}
EXPORT_SYMBOL_GPL(au1300_vss_block_control);
...@@ -169,6 +169,7 @@ ...@@ -169,6 +169,7 @@
#define PRID_IMP_NETLOGIC_XLS412B 0x4c00 #define PRID_IMP_NETLOGIC_XLS412B 0x4c00
#define PRID_IMP_NETLOGIC_XLS408B 0x4e00 #define PRID_IMP_NETLOGIC_XLS408B 0x4e00
#define PRID_IMP_NETLOGIC_XLS404B 0x4f00 #define PRID_IMP_NETLOGIC_XLS404B 0x4f00
#define PRID_IMP_NETLOGIC_AU13XX 0x8000
/* /*
* Definitions for 7:0 on legacy processors * Definitions for 7:0 on legacy processors
......
This diff is collapsed.
...@@ -130,8 +130,10 @@ struct au1xmmc_platform_data { ...@@ -130,8 +130,10 @@ struct au1xmmc_platform_data {
#define SD_CONFIG2_DF (0x00000008) #define SD_CONFIG2_DF (0x00000008)
#define SD_CONFIG2_DC (0x00000010) #define SD_CONFIG2_DC (0x00000010)
#define SD_CONFIG2_xx2 (0x000000e0) #define SD_CONFIG2_xx2 (0x000000e0)
#define SD_CONFIG2_BB (0x00000080)
#define SD_CONFIG2_WB (0x00000100) #define SD_CONFIG2_WB (0x00000100)
#define SD_CONFIG2_RW (0x00000200) #define SD_CONFIG2_RW (0x00000200)
#define SD_CONFIG2_DP (0x00000400)
/* /*
......
...@@ -183,6 +183,37 @@ typedef volatile struct au1xxx_ddma_desc { ...@@ -183,6 +183,37 @@ typedef volatile struct au1xxx_ddma_desc {
#define AU1200_DSCR_CMD0_PSC1_SYNC 25 #define AU1200_DSCR_CMD0_PSC1_SYNC 25
#define AU1200_DSCR_CMD0_CIM_SYNC 26 #define AU1200_DSCR_CMD0_CIM_SYNC 26
#define AU1300_DSCR_CMD0_UART0_TX 0
#define AU1300_DSCR_CMD0_UART0_RX 1
#define AU1300_DSCR_CMD0_UART1_TX 2
#define AU1300_DSCR_CMD0_UART1_RX 3
#define AU1300_DSCR_CMD0_UART2_TX 4
#define AU1300_DSCR_CMD0_UART2_RX 5
#define AU1300_DSCR_CMD0_UART3_TX 6
#define AU1300_DSCR_CMD0_UART3_RX 7
#define AU1300_DSCR_CMD0_SDMS_TX0 8
#define AU1300_DSCR_CMD0_SDMS_RX0 9
#define AU1300_DSCR_CMD0_SDMS_TX1 10
#define AU1300_DSCR_CMD0_SDMS_RX1 11
#define AU1300_DSCR_CMD0_AES_TX 12
#define AU1300_DSCR_CMD0_AES_RX 13
#define AU1300_DSCR_CMD0_PSC0_TX 14
#define AU1300_DSCR_CMD0_PSC0_RX 15
#define AU1300_DSCR_CMD0_PSC1_TX 16
#define AU1300_DSCR_CMD0_PSC1_RX 17
#define AU1300_DSCR_CMD0_PSC2_TX 18
#define AU1300_DSCR_CMD0_PSC2_RX 19
#define AU1300_DSCR_CMD0_PSC3_TX 20
#define AU1300_DSCR_CMD0_PSC3_RX 21
#define AU1300_DSCR_CMD0_LCD 22
#define AU1300_DSCR_CMD0_NAND_FLASH 23
#define AU1300_DSCR_CMD0_SDMS_TX2 24
#define AU1300_DSCR_CMD0_SDMS_RX2 25
#define AU1300_DSCR_CMD0_CIM_SYNC 26
#define AU1300_DSCR_CMD0_UDMA 27
#define AU1300_DSCR_CMD0_DMA_REQ0 28
#define AU1300_DSCR_CMD0_DMA_REQ1 29
#define DSCR_CMD0_THROTTLE 30 #define DSCR_CMD0_THROTTLE 30
#define DSCR_CMD0_ALWAYS 31 #define DSCR_CMD0_ALWAYS 31
#define DSCR_NDEV_IDS 32 #define DSCR_NDEV_IDS 32
......
/*
* gpio-au1300.h -- GPIO control for Au1300 GPIC and compatibles.
*
* Copyright (c) 2009-2011 Manuel Lauss <manuel.lauss@googlemail.com>
*/
#ifndef _GPIO_AU1300_H_
#define _GPIO_AU1300_H_
#include <asm/addrspace.h>
#include <asm/io.h>
#include <asm/mach-au1x00/au1000.h>
/* with the current GPIC design, up to 128 GPIOs are possible.
* The only implementation so far is in the Au1300, which has 75 externally
* available GPIOs.
*/
#define AU1300_GPIO_BASE 0
#define AU1300_GPIO_NUM 75
#define AU1300_GPIO_MAX (AU1300_GPIO_BASE + AU1300_GPIO_NUM - 1)
#define AU1300_GPIC_ADDR \
(void __iomem *)KSEG1ADDR(AU1300_GPIC_PHYS_ADDR)
static inline int au1300_gpio_get_value(unsigned int gpio)
{
void __iomem *roff = AU1300_GPIC_ADDR;
int bit;
gpio -= AU1300_GPIO_BASE;
roff += GPIC_GPIO_BANKOFF(gpio);
bit = GPIC_GPIO_TO_BIT(gpio);
return __raw_readl(roff + AU1300_GPIC_PINVAL) & bit;
}
static inline int au1300_gpio_direction_input(unsigned int gpio)
{
void __iomem *roff = AU1300_GPIC_ADDR;
unsigned long bit;
gpio -= AU1300_GPIO_BASE;
roff += GPIC_GPIO_BANKOFF(gpio);
bit = GPIC_GPIO_TO_BIT(gpio);
__raw_writel(bit, roff + AU1300_GPIC_DEVCLR);
wmb();
return 0;
}
static inline int au1300_gpio_set_value(unsigned int gpio, int v)
{
void __iomem *roff = AU1300_GPIC_ADDR;
unsigned long bit;
gpio -= AU1300_GPIO_BASE;
roff += GPIC_GPIO_BANKOFF(gpio);
bit = GPIC_GPIO_TO_BIT(gpio);
__raw_writel(bit, roff + (v ? AU1300_GPIC_PINVAL
: AU1300_GPIC_PINVALCLR));
wmb();
return 0;
}
static inline int au1300_gpio_direction_output(unsigned int gpio, int v)
{
/* hw switches to output automatically */
return au1300_gpio_set_value(gpio, v);
}
static inline int au1300_gpio_to_irq(unsigned int gpio)
{
return AU1300_FIRST_INT + (gpio - AU1300_GPIO_BASE);
}
static inline int au1300_irq_to_gpio(unsigned int irq)
{
return (irq - AU1300_FIRST_INT) + AU1300_GPIO_BASE;
}
static inline int au1300_gpio_is_valid(unsigned int gpio)
{
int ret;
switch (alchemy_get_cputype()) {
case ALCHEMY_CPU_AU1300:
ret = ((gpio >= AU1300_GPIO_BASE) && (gpio <= AU1300_GPIO_MAX));
break;
default:
ret = 0;
}
return ret;
}
static inline int au1300_gpio_cansleep(unsigned int gpio)
{
return 0;
}
/* hardware remembers gpio 0-63 levels on powerup */
static inline int au1300_gpio_getinitlvl(unsigned int gpio)
{
void __iomem *roff = AU1300_GPIC_ADDR;
unsigned long v;
if (unlikely(gpio > 63))
return 0;
else if (gpio > 31) {
gpio -= 32;
roff += 4;
}
v = __raw_readl(roff + AU1300_GPIC_RSTVAL);
return (v >> gpio) & 1;
}
/**********************************************************************/
/* Linux gpio framework integration.
*
* 4 use cases of Alchemy GPIOS:
*(1) GPIOLIB=y, ALCHEMY_GPIO_INDIRECT=y:
* Board must register gpiochips.
*(2) GPIOLIB=y, ALCHEMY_GPIO_INDIRECT=n:
* A gpiochip for the 75 GPIOs is registered.
*
*(3) GPIOLIB=n, ALCHEMY_GPIO_INDIRECT=y:
* the boards' gpio.h must provide the linux gpio wrapper functions,
*
*(4) GPIOLIB=n, ALCHEMY_GPIO_INDIRECT=n:
* inlinable gpio functions are provided which enable access to the
* Au1300 gpios only by using the numbers straight out of the data-
* sheets.
* Cases 1 and 3 are intended for boards which want to provide their own
* GPIO namespace and -operations (i.e. for example you have 8 GPIOs
* which are in part provided by spare Au1300 GPIO pins and in part by
* an external FPGA but you still want them to be accssible in linux
* as gpio0-7. The board can of course use the alchemy_gpioX_* functions
* as required).
*/
#ifndef CONFIG_GPIOLIB
#ifdef CONFIG_ALCHEMY_GPIOINT_AU1300
#ifndef CONFIG_ALCHEMY_GPIO_INDIRECT /* case (4) */
static inline int gpio_direction_input(unsigned int gpio)
{
return au1300_gpio_direction_input(gpio);
}
static inline int gpio_direction_output(unsigned int gpio, int v)
{
return au1300_gpio_direction_output(gpio, v);
}
static inline int gpio_get_value(unsigned int gpio)
{
return au1300_gpio_get_value(gpio);
}
static inline void gpio_set_value(unsigned int gpio, int v)
{
au1300_gpio_set_value(gpio, v);
}
static inline int gpio_get_value_cansleep(unsigned gpio)
{
return gpio_get_value(gpio);
}
static inline void gpio_set_value_cansleep(unsigned gpio, int value)
{
gpio_set_value(gpio, value);
}
static inline int gpio_is_valid(unsigned int gpio)
{
return au1300_gpio_is_valid(gpio);
}
static inline int gpio_cansleep(unsigned int gpio)
{
return au1300_gpio_cansleep(gpio);
}
static inline int gpio_to_irq(unsigned int gpio)
{
return au1300_gpio_to_irq(gpio);
}
static inline int irq_to_gpio(unsigned int irq)
{
return au1300_irq_to_gpio(irq);
}
static inline int gpio_request(unsigned int gpio, const char *label)
{
return 0;
}
static inline void gpio_free(unsigned int gpio)
{
}
static inline int gpio_set_debounce(unsigned gpio, unsigned debounce)
{
return -ENOSYS;
}
static inline void gpio_unexport(unsigned gpio)
{
}
static inline int gpio_export(unsigned gpio, bool direction_may_change)
{
return -ENOSYS;
}
static inline int gpio_sysfs_set_active_low(unsigned gpio, int value)
{
return -ENOSYS;
}
static inline int gpio_export_link(struct device *dev, const char *name,
unsigned gpio)
{
return -ENOSYS;
}
#endif /* !CONFIG_ALCHEMY_GPIO_INDIRECT */
#endif /* CONFIG_ALCHEMY_GPIOINT_AU1300 */
#endif /* CONFIG GPIOLIB */
#endif /* _GPIO_AU1300_H_ */
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include <asm/mach-au1x00/au1000.h> #include <asm/mach-au1x00/au1000.h>
#include <asm/mach-au1x00/gpio-au1000.h> #include <asm/mach-au1x00/gpio-au1000.h>
#include <asm/mach-au1x00/gpio-au1300.h>
/* On Au1000, Au1500 and Au1100 GPIOs won't work as inputs before /* On Au1000, Au1500 and Au1100 GPIOs won't work as inputs before
* SYS_PININPUTEN is written to at least once. On Au1550/Au1200/Au1300 this * SYS_PININPUTEN is written to at least once. On Au1550/Au1200/Au1300 this
...@@ -58,6 +59,8 @@ static inline int __au_irq_to_gpio(unsigned int irq) ...@@ -58,6 +59,8 @@ static inline int __au_irq_to_gpio(unsigned int irq)
switch (alchemy_get_cputype()) { switch (alchemy_get_cputype()) {
case ALCHEMY_CPU_AU1000...ALCHEMY_CPU_AU1200: case ALCHEMY_CPU_AU1000...ALCHEMY_CPU_AU1200:
return alchemy_irq_to_gpio(irq); return alchemy_irq_to_gpio(irq);
case ALCHEMY_CPU_AU1300:
return au1300_irq_to_gpio(irq);
} }
return -EINVAL; return -EINVAL;
} }
......
...@@ -1014,6 +1014,13 @@ static inline void cpu_probe_netlogic(struct cpuinfo_mips *c, int cpu) ...@@ -1014,6 +1014,13 @@ static inline void cpu_probe_netlogic(struct cpuinfo_mips *c, int cpu)
{ {
decode_configs(c); decode_configs(c);
if ((c->processor_id & 0xff00) == PRID_IMP_NETLOGIC_AU13XX) {
c->cputype = CPU_ALCHEMY;
__cpu_name[cpu] = "Au1300";
/* following stuff is not for Alchemy */
return;
}
c->options = (MIPS_CPU_TLB | c->options = (MIPS_CPU_TLB |
MIPS_CPU_4KEX | MIPS_CPU_4KEX |
MIPS_CPU_COUNTER | MIPS_CPU_COUNTER |
......
...@@ -299,11 +299,11 @@ config I2C_AT91 ...@@ -299,11 +299,11 @@ config I2C_AT91
unless your system can cope with those limitations. unless your system can cope with those limitations.
config I2C_AU1550 config I2C_AU1550
tristate "Au1550/Au1200 SMBus interface" tristate "Au1550/Au1200/Au1300 SMBus interface"
depends on MIPS_ALCHEMY depends on MIPS_ALCHEMY
help help
If you say yes to this option, support will be included for the If you say yes to this option, support will be included for the
Au1550 and Au1200 SMBus interface. Au1550/Au1200/Au1300 SMBus interface.
This driver can also be built as a module. If so, the module This driver can also be built as a module. If so, the module
will be called i2c-au1550. will be called i2c-au1550.
......
...@@ -153,6 +153,7 @@ static inline int has_dbdma(void) ...@@ -153,6 +153,7 @@ static inline int has_dbdma(void)
{ {
switch (alchemy_get_cputype()) { switch (alchemy_get_cputype()) {
case ALCHEMY_CPU_AU1200: case ALCHEMY_CPU_AU1200:
case ALCHEMY_CPU_AU1300:
return 1; return 1;
default: default:
return 0; return 0;
...@@ -768,11 +769,15 @@ static void au1xmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) ...@@ -768,11 +769,15 @@ static void au1xmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
config2 = au_readl(HOST_CONFIG2(host)); config2 = au_readl(HOST_CONFIG2(host));
switch (ios->bus_width) { switch (ios->bus_width) {
case MMC_BUS_WIDTH_8:
config2 |= SD_CONFIG2_BB;
break;
case MMC_BUS_WIDTH_4: case MMC_BUS_WIDTH_4:
config2 &= ~SD_CONFIG2_BB;
config2 |= SD_CONFIG2_WB; config2 |= SD_CONFIG2_WB;
break; break;
case MMC_BUS_WIDTH_1: case MMC_BUS_WIDTH_1:
config2 &= ~SD_CONFIG2_WB; config2 &= ~(SD_CONFIG2_WB | SD_CONFIG2_BB);
break; break;
} }
au_writel(config2, HOST_CONFIG2(host)); au_writel(config2, HOST_CONFIG2(host));
...@@ -943,7 +948,7 @@ static int __devinit au1xmmc_probe(struct platform_device *pdev) ...@@ -943,7 +948,7 @@ static int __devinit au1xmmc_probe(struct platform_device *pdev)
struct mmc_host *mmc; struct mmc_host *mmc;
struct au1xmmc_host *host; struct au1xmmc_host *host;
struct resource *r; struct resource *r;
int ret; int ret, iflag;
mmc = mmc_alloc_host(sizeof(struct au1xmmc_host), &pdev->dev); mmc = mmc_alloc_host(sizeof(struct au1xmmc_host), &pdev->dev);
if (!mmc) { if (!mmc) {
...@@ -982,37 +987,43 @@ static int __devinit au1xmmc_probe(struct platform_device *pdev) ...@@ -982,37 +987,43 @@ static int __devinit au1xmmc_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "no IRQ defined\n"); dev_err(&pdev->dev, "no IRQ defined\n");
goto out3; goto out3;
} }
host->irq = r->start; host->irq = r->start;
/* IRQ is shared among both SD controllers */
ret = request_irq(host->irq, au1xmmc_irq, IRQF_SHARED,
DRIVER_NAME, host);
if (ret) {
dev_err(&pdev->dev, "cannot grab IRQ\n");
goto out3;
}
mmc->ops = &au1xmmc_ops; mmc->ops = &au1xmmc_ops;
mmc->f_min = 450000; mmc->f_min = 450000;
mmc->f_max = 24000000; mmc->f_max = 24000000;
mmc->max_blk_size = 2048;
mmc->max_blk_count = 512;
mmc->ocr_avail = AU1XMMC_OCR;
mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ;
mmc->max_segs = AU1XMMC_DESCRIPTOR_COUNT;
iflag = IRQF_SHARED; /* Au1100/Au1200: one int for both ctrls */
switch (alchemy_get_cputype()) { switch (alchemy_get_cputype()) {
case ALCHEMY_CPU_AU1100: case ALCHEMY_CPU_AU1100:
mmc->max_seg_size = AU1100_MMC_DESCRIPTOR_SIZE; mmc->max_seg_size = AU1100_MMC_DESCRIPTOR_SIZE;
mmc->max_segs = AU1XMMC_DESCRIPTOR_COUNT;
break; break;
case ALCHEMY_CPU_AU1200: case ALCHEMY_CPU_AU1200:
mmc->max_seg_size = AU1200_MMC_DESCRIPTOR_SIZE; mmc->max_seg_size = AU1200_MMC_DESCRIPTOR_SIZE;
mmc->max_segs = AU1XMMC_DESCRIPTOR_COUNT; break;
case ALCHEMY_CPU_AU1300:
iflag = 0; /* nothing is shared */
mmc->max_seg_size = AU1200_MMC_DESCRIPTOR_SIZE;
mmc->f_max = 52000000;
if (host->ioarea->start == AU1100_SD0_PHYS_ADDR)
mmc->caps |= MMC_CAP_8_BIT_DATA;
break; break;
} }
mmc->max_blk_size = 2048; ret = request_irq(host->irq, au1xmmc_irq, iflag, DRIVER_NAME, host);
mmc->max_blk_count = 512; if (ret) {
dev_err(&pdev->dev, "cannot grab IRQ\n");
mmc->ocr_avail = AU1XMMC_OCR; goto out3;
mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; }
host->status = HOST_S_IDLE; host->status = HOST_S_IDLE;
......
...@@ -87,12 +87,12 @@ config SPI_BFIN_SPORT ...@@ -87,12 +87,12 @@ config SPI_BFIN_SPORT
Enable support for a SPI bus via the Blackfin SPORT peripheral. Enable support for a SPI bus via the Blackfin SPORT peripheral.
config SPI_AU1550 config SPI_AU1550
tristate "Au1550/Au12x0 SPI Controller" tristate "Au1550/Au1200/Au1300 SPI Controller"
depends on MIPS_ALCHEMY && EXPERIMENTAL depends on MIPS_ALCHEMY && EXPERIMENTAL
select SPI_BITBANG select SPI_BITBANG
help help
If you say yes to this option, support will be included for the If you say yes to this option, support will be included for the
Au1550 SPI controller (may also work with Au1200,Au1210,Au1250). PSC SPI controller found on Au1550, Au1200 and Au1300 series.
config SPI_BITBANG config SPI_BITBANG
tristate "Utilities for Bitbanging SPI masters" tristate "Utilities for Bitbanging SPI masters"
......
...@@ -52,9 +52,263 @@ ...@@ -52,9 +52,263 @@
USBCFG_EBE | USBCFG_EME | USBCFG_OBE | \ USBCFG_EBE | USBCFG_EME | USBCFG_OBE | \
USBCFG_OME) USBCFG_OME)
/* Au1300 USB config registers */
#define USB_DWC_CTRL1 0x00
#define USB_DWC_CTRL2 0x04
#define USB_VBUS_TIMER 0x10
#define USB_SBUS_CTRL 0x14
#define USB_MSR_ERR 0x18
#define USB_DWC_CTRL3 0x1C
#define USB_DWC_CTRL4 0x20
#define USB_OTG_STATUS 0x28
#define USB_DWC_CTRL5 0x2C
#define USB_DWC_CTRL6 0x30
#define USB_DWC_CTRL7 0x34
#define USB_PHY_STATUS 0xC0
#define USB_INT_STATUS 0xC4
#define USB_INT_ENABLE 0xC8
#define USB_DWC_CTRL1_OTGD 0x04 /* set to DISable OTG */
#define USB_DWC_CTRL1_HSTRS 0x02 /* set to ENable EHCI */
#define USB_DWC_CTRL1_DCRS 0x01 /* set to ENable UDC */
#define USB_DWC_CTRL2_PHY1RS 0x04 /* set to enable PHY1 */
#define USB_DWC_CTRL2_PHY0RS 0x02 /* set to enable PHY0 */
#define USB_DWC_CTRL2_PHYRS 0x01 /* set to enable PHY */
#define USB_DWC_CTRL3_OHCI1_CKEN (1 << 19)
#define USB_DWC_CTRL3_OHCI0_CKEN (1 << 18)
#define USB_DWC_CTRL3_EHCI0_CKEN (1 << 17)
#define USB_DWC_CTRL3_OTG0_CKEN (1 << 16)
#define USB_SBUS_CTRL_SBCA 0x04 /* coherent access */
#define USB_INTEN_FORCE 0x20
#define USB_INTEN_PHY 0x10
#define USB_INTEN_UDC 0x08
#define USB_INTEN_EHCI 0x04
#define USB_INTEN_OHCI1 0x02
#define USB_INTEN_OHCI0 0x01
static DEFINE_SPINLOCK(alchemy_usb_lock); static DEFINE_SPINLOCK(alchemy_usb_lock);
static inline void __au1300_usb_phyctl(void __iomem *base, int enable)
{
unsigned long r, s;
r = __raw_readl(base + USB_DWC_CTRL2);
s = __raw_readl(base + USB_DWC_CTRL3);
s &= USB_DWC_CTRL3_OHCI1_CKEN | USB_DWC_CTRL3_OHCI0_CKEN |
USB_DWC_CTRL3_EHCI0_CKEN | USB_DWC_CTRL3_OTG0_CKEN;
if (enable) {
/* simply enable all PHYs */
r |= USB_DWC_CTRL2_PHY1RS | USB_DWC_CTRL2_PHY0RS |
USB_DWC_CTRL2_PHYRS;
__raw_writel(r, base + USB_DWC_CTRL2);
wmb();
} else if (!s) {
/* no USB block active, do disable all PHYs */
r &= ~(USB_DWC_CTRL2_PHY1RS | USB_DWC_CTRL2_PHY0RS |
USB_DWC_CTRL2_PHYRS);
__raw_writel(r, base + USB_DWC_CTRL2);
wmb();
}
}
static inline void __au1300_ohci_control(void __iomem *base, int enable, int id)
{
unsigned long r;
if (enable) {
__raw_writel(1, base + USB_DWC_CTRL7); /* start OHCI clock */
wmb();
r = __raw_readl(base + USB_DWC_CTRL3); /* enable OHCI block */
r |= (id == 0) ? USB_DWC_CTRL3_OHCI0_CKEN
: USB_DWC_CTRL3_OHCI1_CKEN;
__raw_writel(r, base + USB_DWC_CTRL3);
wmb();
__au1300_usb_phyctl(base, enable); /* power up the PHYs */
r = __raw_readl(base + USB_INT_ENABLE);
r |= (id == 0) ? USB_INTEN_OHCI0 : USB_INTEN_OHCI1;
__raw_writel(r, base + USB_INT_ENABLE);
wmb();
/* reset the OHCI start clock bit */
__raw_writel(0, base + USB_DWC_CTRL7);
wmb();
} else {
r = __raw_readl(base + USB_INT_ENABLE);
r &= ~((id == 0) ? USB_INTEN_OHCI0 : USB_INTEN_OHCI1);
__raw_writel(r, base + USB_INT_ENABLE);
wmb();
r = __raw_readl(base + USB_DWC_CTRL3);
r &= ~((id == 0) ? USB_DWC_CTRL3_OHCI0_CKEN
: USB_DWC_CTRL3_OHCI1_CKEN);
__raw_writel(r, base + USB_DWC_CTRL3);
wmb();
__au1300_usb_phyctl(base, enable);
}
}
static inline void __au1300_ehci_control(void __iomem *base, int enable)
{
unsigned long r;
if (enable) {
r = __raw_readl(base + USB_DWC_CTRL3);
r |= USB_DWC_CTRL3_EHCI0_CKEN;
__raw_writel(r, base + USB_DWC_CTRL3);
wmb();
r = __raw_readl(base + USB_DWC_CTRL1);
r |= USB_DWC_CTRL1_HSTRS;
__raw_writel(r, base + USB_DWC_CTRL1);
wmb();
__au1300_usb_phyctl(base, enable);
r = __raw_readl(base + USB_INT_ENABLE);
r |= USB_INTEN_EHCI;
__raw_writel(r, base + USB_INT_ENABLE);
wmb();
} else {
r = __raw_readl(base + USB_INT_ENABLE);
r &= ~USB_INTEN_EHCI;
__raw_writel(r, base + USB_INT_ENABLE);
wmb();
r = __raw_readl(base + USB_DWC_CTRL1);
r &= ~USB_DWC_CTRL1_HSTRS;
__raw_writel(r, base + USB_DWC_CTRL1);
wmb();
r = __raw_readl(base + USB_DWC_CTRL3);
r &= ~USB_DWC_CTRL3_EHCI0_CKEN;
__raw_writel(r, base + USB_DWC_CTRL3);
wmb();
__au1300_usb_phyctl(base, enable);
}
}
static inline void __au1300_udc_control(void __iomem *base, int enable)
{
unsigned long r;
if (enable) {
r = __raw_readl(base + USB_DWC_CTRL1);
r |= USB_DWC_CTRL1_DCRS;
__raw_writel(r, base + USB_DWC_CTRL1);
wmb();
__au1300_usb_phyctl(base, enable);
r = __raw_readl(base + USB_INT_ENABLE);
r |= USB_INTEN_UDC;
__raw_writel(r, base + USB_INT_ENABLE);
wmb();
} else {
r = __raw_readl(base + USB_INT_ENABLE);
r &= ~USB_INTEN_UDC;
__raw_writel(r, base + USB_INT_ENABLE);
wmb();
r = __raw_readl(base + USB_DWC_CTRL1);
r &= ~USB_DWC_CTRL1_DCRS;
__raw_writel(r, base + USB_DWC_CTRL1);
wmb();
__au1300_usb_phyctl(base, enable);
}
}
static inline void __au1300_otg_control(void __iomem *base, int enable)
{
unsigned long r;
if (enable) {
r = __raw_readl(base + USB_DWC_CTRL3);
r |= USB_DWC_CTRL3_OTG0_CKEN;
__raw_writel(r, base + USB_DWC_CTRL3);
wmb();
r = __raw_readl(base + USB_DWC_CTRL1);
r &= ~USB_DWC_CTRL1_OTGD;
__raw_writel(r, base + USB_DWC_CTRL1);
wmb();
__au1300_usb_phyctl(base, enable);
} else {
r = __raw_readl(base + USB_DWC_CTRL1);
r |= USB_DWC_CTRL1_OTGD;
__raw_writel(r, base + USB_DWC_CTRL1);
wmb();
r = __raw_readl(base + USB_DWC_CTRL3);
r &= ~USB_DWC_CTRL3_OTG0_CKEN;
__raw_writel(r, base + USB_DWC_CTRL3);
wmb();
__au1300_usb_phyctl(base, enable);
}
}
static inline int au1300_usb_control(int block, int enable)
{
void __iomem *base =
(void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
int ret = 0;
switch (block) {
case ALCHEMY_USB_OHCI0:
__au1300_ohci_control(base, enable, 0);
break;
case ALCHEMY_USB_OHCI1:
__au1300_ohci_control(base, enable, 1);
break;
case ALCHEMY_USB_EHCI0:
__au1300_ehci_control(base, enable);
break;
case ALCHEMY_USB_UDC0:
__au1300_udc_control(base, enable);
break;
case ALCHEMY_USB_OTG0:
__au1300_otg_control(base, enable);
break;
default:
ret = -ENODEV;
}
return ret;
}
static inline void au1300_usb_init(void)
{
void __iomem *base =
(void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
/* set some sane defaults. Note: we don't fiddle with DWC_CTRL4
* here at all: Port 2 routing (EHCI or UDC) must be set either
* by boot firmware or platform init code; I can't autodetect
* a sane setting.
*/
__raw_writel(0, base + USB_INT_ENABLE); /* disable all USB irqs */
wmb();
__raw_writel(0, base + USB_DWC_CTRL3); /* disable all clocks */
wmb();
__raw_writel(~0, base + USB_MSR_ERR); /* clear all errors */
wmb();
__raw_writel(~0, base + USB_INT_STATUS); /* clear int status */
wmb();
/* set coherent access bit */
__raw_writel(USB_SBUS_CTRL_SBCA, base + USB_SBUS_CTRL);
wmb();
}
static inline void __au1200_ohci_control(void __iomem *base, int enable) static inline void __au1200_ohci_control(void __iomem *base, int enable)
{ {
...@@ -233,6 +487,9 @@ int alchemy_usb_control(int block, int enable) ...@@ -233,6 +487,9 @@ int alchemy_usb_control(int block, int enable)
case ALCHEMY_CPU_AU1200: case ALCHEMY_CPU_AU1200:
ret = au1200_usb_control(block, enable); ret = au1200_usb_control(block, enable);
break; break;
case ALCHEMY_CPU_AU1300:
ret = au1300_usb_control(block, enable);
break;
default: default:
ret = -ENODEV; ret = -ENODEV;
} }
...@@ -281,6 +538,20 @@ static void au1200_usb_pm(int susp) ...@@ -281,6 +538,20 @@ static void au1200_usb_pm(int susp)
} }
} }
static void au1300_usb_pm(int susp)
{
void __iomem *base =
(void __iomem *)KSEG1ADDR(AU1300_USB_CTL_PHYS_ADDR);
/* remember Port2 routing */
if (susp) {
alchemy_usb_pmdata[0] = __raw_readl(base + USB_DWC_CTRL4);
} else {
au1300_usb_init();
__raw_writel(alchemy_usb_pmdata[0], base + USB_DWC_CTRL4);
wmb();
}
}
static void alchemy_usb_pm(int susp) static void alchemy_usb_pm(int susp)
{ {
switch (alchemy_get_cputype()) { switch (alchemy_get_cputype()) {
...@@ -295,6 +566,9 @@ static void alchemy_usb_pm(int susp) ...@@ -295,6 +566,9 @@ static void alchemy_usb_pm(int susp)
case ALCHEMY_CPU_AU1200: case ALCHEMY_CPU_AU1200:
au1200_usb_pm(susp); au1200_usb_pm(susp);
break; break;
case ALCHEMY_CPU_AU1300:
au1300_usb_pm(susp);
break;
} }
} }
...@@ -328,6 +602,9 @@ static int __init alchemy_usb_init(void) ...@@ -328,6 +602,9 @@ static int __init alchemy_usb_init(void)
case ALCHEMY_CPU_AU1200: case ALCHEMY_CPU_AU1200:
au1200_usb_init(); au1200_usb_init();
break; break;
case ALCHEMY_CPU_AU1300:
au1300_usb_init();
break;
} }
register_syscore_ops(&alchemy_usb_pm_ops); register_syscore_ops(&alchemy_usb_pm_ops);
......
...@@ -89,7 +89,7 @@ static const struct hc_driver ohci_au1xxx_hc_driver = { ...@@ -89,7 +89,7 @@ static const struct hc_driver ohci_au1xxx_hc_driver = {
static int ohci_hcd_au1xxx_drv_probe(struct platform_device *pdev) static int ohci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
{ {
int ret; int ret, unit;
struct usb_hcd *hcd; struct usb_hcd *hcd;
if (usb_disabled()) if (usb_disabled())
...@@ -120,7 +120,9 @@ static int ohci_hcd_au1xxx_drv_probe(struct platform_device *pdev) ...@@ -120,7 +120,9 @@ static int ohci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
goto err2; goto err2;
} }
if (alchemy_usb_control(ALCHEMY_USB_OHCI0, 1)) { unit = (hcd->rsrc_start == AU1300_USB_OHCI1_PHYS_ADDR) ?
ALCHEMY_USB_OHCI1 : ALCHEMY_USB_OHCI0;
if (alchemy_usb_control(unit, 1)) {
printk(KERN_INFO "%s: controller init failed!\n", pdev->name); printk(KERN_INFO "%s: controller init failed!\n", pdev->name);
ret = -ENODEV; ret = -ENODEV;
goto err3; goto err3;
...@@ -135,7 +137,7 @@ static int ohci_hcd_au1xxx_drv_probe(struct platform_device *pdev) ...@@ -135,7 +137,7 @@ static int ohci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
return ret; return ret;
} }
alchemy_usb_control(ALCHEMY_USB_OHCI0, 0); alchemy_usb_control(unit, 0);
err3: err3:
iounmap(hcd->regs); iounmap(hcd->regs);
err2: err2:
...@@ -148,9 +150,12 @@ static int ohci_hcd_au1xxx_drv_probe(struct platform_device *pdev) ...@@ -148,9 +150,12 @@ static int ohci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
static int ohci_hcd_au1xxx_drv_remove(struct platform_device *pdev) static int ohci_hcd_au1xxx_drv_remove(struct platform_device *pdev)
{ {
struct usb_hcd *hcd = platform_get_drvdata(pdev); struct usb_hcd *hcd = platform_get_drvdata(pdev);
int unit;
unit = (hcd->rsrc_start == AU1300_USB_OHCI1_PHYS_ADDR) ?
ALCHEMY_USB_OHCI1 : ALCHEMY_USB_OHCI0;
usb_remove_hcd(hcd); usb_remove_hcd(hcd);
alchemy_usb_control(ALCHEMY_USB_OHCI0, 0); alchemy_usb_control(unit, 0);
iounmap(hcd->regs); iounmap(hcd->regs);
release_mem_region(hcd->rsrc_start, hcd->rsrc_len); release_mem_region(hcd->rsrc_start, hcd->rsrc_len);
usb_put_hcd(hcd); usb_put_hcd(hcd);
......
...@@ -1763,16 +1763,16 @@ config FB_AU1100 ...@@ -1763,16 +1763,16 @@ config FB_AU1100
au1100fb:panel=<name>. au1100fb:panel=<name>.
config FB_AU1200 config FB_AU1200
bool "Au1200 LCD Driver" bool "Au1200/Au1300 LCD Driver"
depends on (FB = y) && MIPS_ALCHEMY depends on (FB = y) && MIPS_ALCHEMY
select FB_SYS_FILLRECT select FB_SYS_FILLRECT
select FB_SYS_COPYAREA select FB_SYS_COPYAREA
select FB_SYS_IMAGEBLIT select FB_SYS_IMAGEBLIT
select FB_SYS_FOPS select FB_SYS_FOPS
help help
This is the framebuffer driver for the AMD Au1200 SOC. It can drive This is the framebuffer driver for the Au1200/Au1300 SOCs.
various panels and CRTs by passing in kernel cmd line option It can drive various panels and CRTs by passing in kernel cmd line
au1200fb:panel=<name>. option au1200fb:panel=<name>.
config FB_VT8500 config FB_VT8500
bool "VT8500 LCD Driver" bool "VT8500 LCD Driver"
......
## ##
## Au1200/Au1550 PSC + DBDMA ## Au1200/Au1550/Au1300 PSC + DBDMA
## ##
config SND_SOC_AU1XPSC config SND_SOC_AU1XPSC
tristate "SoC Audio for Au1200/Au1250/Au1550" tristate "SoC Audio for Au12xx/Au13xx/Au1550"
depends on MIPS_ALCHEMY depends on MIPS_ALCHEMY
help help
This option enables support for the Programmable Serial This option enables support for the Programmable Serial
Controllers in AC97 and I2S mode, and the Descriptor-Based DMA Controllers in AC97 and I2S mode, and the Descriptor-Based DMA
Controller (DBDMA) as found on the Au1200/Au1250/Au1550 SoC. Controller (DBDMA) as found on the Au12xx/Au13xx/Au1550 SoC.
config SND_SOC_AU1XPSC_I2S config SND_SOC_AU1XPSC_I2S
tristate tristate
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment