Commit 4e8a780e authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'rmobile-latest' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6

* 'rmobile-latest' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6: (34 commits)
  ARM: mach-shmobile: mackerel: add renesas_usbhs support for USB1
  ARM: mach-shmobile: Correct the G4EVM SDHI0 I/O range.
  ARM: arch-shmobile: sh7372: add renesas_usbhs irq support
  ARM: mach-shmobile: sh73a0: mark DMA slave ID 0 as invalid
  ARM: mach-shmobile: mark DMA slave ID 0 as invalid
  ARM: mach-shmobile: Enable DMAEngine for SDHI on AG5EVM
  ARM: mach-shmobile: Enable DMAEngine for MMCIF on AG5EVM
  ARM: mach-shmobile: sh73a0 DMA Engine support for SY-DMAC
  dmaengine: shdma: Update SH_DMAC_MAX_CHANNELS to 20
  dmaengine: shdma: Fix SH_DMAC_MAX_CHANNELS handling
  dmaengine: shdma: Make second memory window optional
  ARM: mach-shmobile: Tidy up after SH7372 pm changes.
  ARM: mach-shmobile: sh7372 Core Standby CPUIdle
  ARM: mach-shmobile: CPUIdle support
  ARM: mach-shmobile: sh7372 Core Standby Suspend-to-RAM
  ARM: mach-shmobile: Suspend-to-RAM support
  mailmap: Add entry for Damian Hobson-Garcia.
  ARM: switch mackerel to dynamically manage the platform camera
  ARM: mach-shmobile: Add SDHI support for AG5EVM and sh73a0
  ARM: arch-shmobile: Use multiple irq vectors for SDHI
  ...
parents 90ff1f30 66ee3bef
...@@ -32,6 +32,7 @@ Brian Avery <b.avery@hp.com> ...@@ -32,6 +32,7 @@ Brian Avery <b.avery@hp.com>
Brian King <brking@us.ibm.com> Brian King <brking@us.ibm.com>
Christoph Hellwig <hch@lst.de> Christoph Hellwig <hch@lst.de>
Corey Minyard <minyard@acm.org> Corey Minyard <minyard@acm.org>
Damian Hobson-Garcia <dhobsong@igel.co.jp>
David Brownell <david-b@pacbell.net> David Brownell <david-b@pacbell.net>
David Woodhouse <dwmw2@shinybook.infradead.org> David Woodhouse <dwmw2@shinybook.infradead.org>
Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
......
...@@ -30,6 +30,11 @@ obj-$(CONFIG_ARCH_SH7377) += entry-intc.o ...@@ -30,6 +30,11 @@ obj-$(CONFIG_ARCH_SH7377) += entry-intc.o
obj-$(CONFIG_ARCH_SH7372) += entry-intc.o obj-$(CONFIG_ARCH_SH7372) += entry-intc.o
obj-$(CONFIG_ARCH_SH73A0) += entry-gic.o obj-$(CONFIG_ARCH_SH73A0) += entry-gic.o
# PM objects
obj-$(CONFIG_SUSPEND) += suspend.o
obj-$(CONFIG_CPU_IDLE) += cpuidle.o
obj-$(CONFIG_ARCH_SH7372) += pm-sh7372.o sleep-sh7372.o
# Board objects # Board objects
obj-$(CONFIG_MACH_G3EVM) += board-g3evm.o obj-$(CONFIG_MACH_G3EVM) += board-g3evm.o
obj-$(CONFIG_MACH_G4EVM) += board-g4evm.o obj-$(CONFIG_MACH_G4EVM) += board-g4evm.o
......
...@@ -34,6 +34,8 @@ ...@@ -34,6 +34,8 @@
#include <linux/input/sh_keysc.h> #include <linux/input/sh_keysc.h>
#include <linux/mmc/host.h> #include <linux/mmc/host.h>
#include <linux/mmc/sh_mmcif.h> #include <linux/mmc/sh_mmcif.h>
#include <linux/mmc/sh_mobile_sdhi.h>
#include <linux/mfd/tmio.h>
#include <linux/sh_clk.h> #include <linux/sh_clk.h>
#include <video/sh_mobile_lcdc.h> #include <video/sh_mobile_lcdc.h>
#include <video/sh_mipi_dsi.h> #include <video/sh_mipi_dsi.h>
...@@ -156,10 +158,19 @@ static struct resource sh_mmcif_resources[] = { ...@@ -156,10 +158,19 @@ static struct resource sh_mmcif_resources[] = {
}, },
}; };
static struct sh_mmcif_dma sh_mmcif_dma = {
.chan_priv_rx = {
.slave_id = SHDMA_SLAVE_MMCIF_RX,
},
.chan_priv_tx = {
.slave_id = SHDMA_SLAVE_MMCIF_TX,
},
};
static struct sh_mmcif_plat_data sh_mmcif_platdata = { static struct sh_mmcif_plat_data sh_mmcif_platdata = {
.sup_pclk = 0, .sup_pclk = 0,
.ocr = MMC_VDD_165_195, .ocr = MMC_VDD_165_195,
.caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE, .caps = MMC_CAP_8_BIT_DATA | MMC_CAP_NONREMOVABLE,
.dma = &sh_mmcif_dma,
}; };
static struct platform_device mmc_device = { static struct platform_device mmc_device = {
...@@ -296,11 +307,13 @@ static struct platform_device lcdc0_device = { ...@@ -296,11 +307,13 @@ static struct platform_device lcdc0_device = {
/* MIPI-DSI */ /* MIPI-DSI */
static struct resource mipidsi0_resources[] = { static struct resource mipidsi0_resources[] = {
[0] = { [0] = {
.name = "DSI0",
.start = 0xfeab0000, .start = 0xfeab0000,
.end = 0xfeab3fff, .end = 0xfeab3fff,
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
}, },
[1] = { [1] = {
.name = "DSI0",
.start = 0xfeab4000, .start = 0xfeab4000,
.end = 0xfeab7fff, .end = 0xfeab7fff,
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
...@@ -325,6 +338,89 @@ static struct platform_device mipidsi0_device = { ...@@ -325,6 +338,89 @@ static struct platform_device mipidsi0_device = {
}, },
}; };
static struct sh_mobile_sdhi_info sdhi0_info = {
.dma_slave_tx = SHDMA_SLAVE_SDHI0_TX,
.dma_slave_rx = SHDMA_SLAVE_SDHI0_RX,
.tmio_caps = MMC_CAP_SD_HIGHSPEED,
.tmio_ocr_mask = MMC_VDD_27_28 | MMC_VDD_28_29,
};
static struct resource sdhi0_resources[] = {
[0] = {
.name = "SDHI0",
.start = 0xee100000,
.end = 0xee1000ff,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = gic_spi(83),
.flags = IORESOURCE_IRQ,
},
[2] = {
.start = gic_spi(84),
.flags = IORESOURCE_IRQ,
},
[3] = {
.start = gic_spi(85),
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device sdhi0_device = {
.name = "sh_mobile_sdhi",
.id = 0,
.num_resources = ARRAY_SIZE(sdhi0_resources),
.resource = sdhi0_resources,
.dev = {
.platform_data = &sdhi0_info,
},
};
void ag5evm_sdhi1_set_pwr(struct platform_device *pdev, int state)
{
gpio_set_value(GPIO_PORT114, state);
}
static struct sh_mobile_sdhi_info sh_sdhi1_platdata = {
.dma_slave_tx = SHDMA_SLAVE_SDHI1_TX,
.dma_slave_rx = SHDMA_SLAVE_SDHI1_RX,
.tmio_flags = TMIO_MMC_WRPROTECT_DISABLE,
.tmio_caps = MMC_CAP_NONREMOVABLE,
.tmio_ocr_mask = MMC_VDD_32_33 | MMC_VDD_33_34,
.set_pwr = ag5evm_sdhi1_set_pwr,
};
static struct resource sdhi1_resources[] = {
[0] = {
.name = "SDHI1",
.start = 0xee120000,
.end = 0xee1200ff,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = gic_spi(87),
.flags = IORESOURCE_IRQ,
},
[2] = {
.start = gic_spi(88),
.flags = IORESOURCE_IRQ,
},
[3] = {
.start = gic_spi(89),
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device sdhi1_device = {
.name = "sh_mobile_sdhi",
.id = 1,
.dev = {
.platform_data = &sh_sdhi1_platdata,
},
.num_resources = ARRAY_SIZE(sdhi1_resources),
.resource = sdhi1_resources,
};
static struct platform_device *ag5evm_devices[] __initdata = { static struct platform_device *ag5evm_devices[] __initdata = {
&eth_device, &eth_device,
&keysc_device, &keysc_device,
...@@ -333,6 +429,8 @@ static struct platform_device *ag5evm_devices[] __initdata = { ...@@ -333,6 +429,8 @@ static struct platform_device *ag5evm_devices[] __initdata = {
&irda_device, &irda_device,
&lcdc0_device, &lcdc0_device,
&mipidsi0_device, &mipidsi0_device,
&sdhi0_device,
&sdhi1_device,
}; };
static struct map_desc ag5evm_io_desc[] __initdata = { static struct map_desc ag5evm_io_desc[] __initdata = {
...@@ -454,6 +552,26 @@ static void __init ag5evm_init(void) ...@@ -454,6 +552,26 @@ static void __init ag5evm_init(void)
/* MIPI-DSI clock setup */ /* MIPI-DSI clock setup */
__raw_writel(0x2a809010, DSI0PHYCR); __raw_writel(0x2a809010, DSI0PHYCR);
/* enable SDHI0 on CN15 [SD I/F] */
gpio_request(GPIO_FN_SDHICD0, NULL);
gpio_request(GPIO_FN_SDHIWP0, NULL);
gpio_request(GPIO_FN_SDHICMD0, NULL);
gpio_request(GPIO_FN_SDHICLK0, NULL);
gpio_request(GPIO_FN_SDHID0_3, NULL);
gpio_request(GPIO_FN_SDHID0_2, NULL);
gpio_request(GPIO_FN_SDHID0_1, NULL);
gpio_request(GPIO_FN_SDHID0_0, NULL);
/* enable SDHI1 on CN4 [WLAN I/F] */
gpio_request(GPIO_FN_SDHICLK1, NULL);
gpio_request(GPIO_FN_SDHICMD1_PU, NULL);
gpio_request(GPIO_FN_SDHID1_3_PU, NULL);
gpio_request(GPIO_FN_SDHID1_2_PU, NULL);
gpio_request(GPIO_FN_SDHID1_1_PU, NULL);
gpio_request(GPIO_FN_SDHID1_0_PU, NULL);
gpio_request(GPIO_PORT114, "sdhi1_power");
gpio_direction_output(GPIO_PORT114, 0);
#ifdef CONFIG_CACHE_L2X0 #ifdef CONFIG_CACHE_L2X0
/* Shared attribute override enable, 64K*8way */ /* Shared attribute override enable, 64K*8way */
l2x0_init(__io(0xf0100000), 0x00460000, 0xc2000fff); l2x0_init(__io(0xf0100000), 0x00460000, 0xc2000fff);
......
...@@ -316,7 +316,15 @@ static struct resource sdhi0_resources[] = { ...@@ -316,7 +316,15 @@ static struct resource sdhi0_resources[] = {
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
}, },
[1] = { [1] = {
.start = evt2irq(0x0e00) /* SDHI0 */, .start = evt2irq(0x0e00) /* SDHI0_SDHI0I0 */,
.flags = IORESOURCE_IRQ,
},
[2] = {
.start = evt2irq(0x0e20) /* SDHI0_SDHI0I1 */,
.flags = IORESOURCE_IRQ,
},
[3] = {
.start = evt2irq(0x0e40) /* SDHI0_SDHI0I2 */,
.flags = IORESOURCE_IRQ, .flags = IORESOURCE_IRQ,
}, },
}; };
...@@ -349,7 +357,15 @@ static struct resource sdhi1_resources[] = { ...@@ -349,7 +357,15 @@ static struct resource sdhi1_resources[] = {
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
}, },
[1] = { [1] = {
.start = evt2irq(0x0e80), .start = evt2irq(0x0e80), /* SDHI1_SDHI1I0 */
.flags = IORESOURCE_IRQ,
},
[2] = {
.start = evt2irq(0x0ea0), /* SDHI1_SDHI1I1 */
.flags = IORESOURCE_IRQ,
},
[3] = {
.start = evt2irq(0x0ec0), /* SDHI1_SDHI1I2 */
.flags = IORESOURCE_IRQ, .flags = IORESOURCE_IRQ,
}, },
}; };
...@@ -980,11 +996,6 @@ static void __init hdmi_init_pm_clock(void) ...@@ -980,11 +996,6 @@ static void __init hdmi_init_pm_clock(void)
goto out; goto out;
} }
ret = clk_enable(&sh7372_pllc2_clk);
if (ret < 0) {
pr_err("Cannot enable pllc2 clock\n");
goto out;
}
pr_debug("PLLC2 set frequency %lu\n", rate); pr_debug("PLLC2 set frequency %lu\n", rate);
ret = clk_set_parent(hdmi_ick, &sh7372_pllc2_clk); ret = clk_set_parent(hdmi_ick, &sh7372_pllc2_clk);
...@@ -1343,6 +1354,7 @@ static void __init ap4evb_init(void) ...@@ -1343,6 +1354,7 @@ static void __init ap4evb_init(void)
hdmi_init_pm_clock(); hdmi_init_pm_clock();
fsi_init_pm_clock(); fsi_init_pm_clock();
sh7372_pm_init();
} }
static void __init ap4evb_timer_init(void) static void __init ap4evb_timer_init(void)
......
...@@ -205,7 +205,7 @@ static struct resource sdhi0_resources[] = { ...@@ -205,7 +205,7 @@ static struct resource sdhi0_resources[] = {
[0] = { [0] = {
.name = "SDHI0", .name = "SDHI0",
.start = 0xe6d50000, .start = 0xe6d50000,
.end = 0xe6d50nff, .end = 0xe6d500ff,
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
}, },
[1] = { [1] = {
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include <linux/sh_intc.h> #include <linux/sh_intc.h>
#include <linux/tca6416_keypad.h> #include <linux/tca6416_keypad.h>
#include <linux/usb/r8a66597.h> #include <linux/usb/r8a66597.h>
#include <linux/usb/renesas_usbhs.h>
#include <video/sh_mobile_hdmi.h> #include <video/sh_mobile_hdmi.h>
#include <video/sh_mobile_lcdc.h> #include <video/sh_mobile_lcdc.h>
...@@ -143,7 +144,30 @@ ...@@ -143,7 +144,30 @@
* open | external VBUS | Function * open | external VBUS | Function
* *
* *1 * *1
* CN31 is used as Host in Linux. * CN31 is used as
* CONFIG_USB_R8A66597_HCD Host
* CONFIG_USB_RENESAS_USBHS Function
*
* CAUTION
*
* renesas_usbhs driver can use external interrupt mode
* (which come from USB-PHY) or autonomy mode (it use own interrupt)
* for detecting connection/disconnection when Function.
* USB will be power OFF while it has been disconnecting
* if external interrupt mode, and it is always power ON if autonomy mode,
*
* mackerel can not use external interrupt (IRQ7-PORT167) mode on "USB0",
* because Touchscreen is using IRQ7-PORT40.
* It is impossible to use IRQ7 demux on this board.
*
* We can use external interrupt mode USB-Function on "USB1".
* USB1 can become Host by r8a66597, and become Function by renesas_usbhs.
* But don't select both drivers in same time.
* These uses same IRQ number for request_irq(), and aren't supporting
* IRQF_SHARD / IORESOURCE_IRQ_SHAREABLE.
*
* Actually these are old/new version of USB driver.
* This mean its register will be broken if it supports SHARD IRQ,
*/ */
/* /*
...@@ -185,6 +209,7 @@ ...@@ -185,6 +209,7 @@
* FIXME !! * FIXME !!
* *
* gpio_no_direction * gpio_no_direction
* gpio_pull_down
* are quick_hack. * are quick_hack.
* *
* current gpio frame work doesn't have * current gpio frame work doesn't have
...@@ -196,6 +221,16 @@ static void __init gpio_no_direction(u32 addr) ...@@ -196,6 +221,16 @@ static void __init gpio_no_direction(u32 addr)
__raw_writeb(0x00, addr); __raw_writeb(0x00, addr);
} }
static void __init gpio_pull_down(u32 addr)
{
u8 data = __raw_readb(addr);
data &= 0x0F;
data |= 0xA0;
__raw_writeb(data, addr);
}
/* MTD */ /* MTD */
static struct mtd_partition nor_flash_partitions[] = { static struct mtd_partition nor_flash_partitions[] = {
{ {
...@@ -458,12 +493,6 @@ static void __init hdmi_init_pm_clock(void) ...@@ -458,12 +493,6 @@ static void __init hdmi_init_pm_clock(void)
goto out; goto out;
} }
ret = clk_enable(&sh7372_pllc2_clk);
if (ret < 0) {
pr_err("Cannot enable pllc2 clock\n");
goto out;
}
pr_debug("PLLC2 set frequency %lu\n", rate); pr_debug("PLLC2 set frequency %lu\n", rate);
ret = clk_set_parent(hdmi_ick, &sh7372_pllc2_clk); ret = clk_set_parent(hdmi_ick, &sh7372_pllc2_clk);
...@@ -515,6 +544,157 @@ static struct platform_device usb1_host_device = { ...@@ -515,6 +544,157 @@ static struct platform_device usb1_host_device = {
.resource = usb1_host_resources, .resource = usb1_host_resources,
}; };
/* USB1 (Function) */
#define USB_PHY_MODE (1 << 4)
#define USB_PHY_INT_EN ((1 << 3) | (1 << 2))
#define USB_PHY_ON (1 << 1)
#define USB_PHY_OFF (1 << 0)
#define USB_PHY_INT_CLR (USB_PHY_ON | USB_PHY_OFF)
struct usbhs_private {
unsigned int irq;
unsigned int usbphyaddr;
unsigned int usbcrcaddr;
struct renesas_usbhs_platform_info info;
};
#define usbhs_get_priv(pdev) \
container_of(renesas_usbhs_get_info(pdev), \
struct usbhs_private, info)
#define usbhs_is_connected(priv) \
(!((1 << 7) & __raw_readw(priv->usbcrcaddr)))
static int usbhs1_get_id(struct platform_device *pdev)
{
return USBHS_GADGET;
}
static int usbhs1_get_vbus(struct platform_device *pdev)
{
return usbhs_is_connected(usbhs_get_priv(pdev));
}
static irqreturn_t usbhs1_interrupt(int irq, void *data)
{
struct platform_device *pdev = data;
struct usbhs_private *priv = usbhs_get_priv(pdev);
dev_dbg(&pdev->dev, "%s\n", __func__);
renesas_usbhs_call_notify_hotplug(pdev);
/* clear status */
__raw_writew(__raw_readw(priv->usbphyaddr) | USB_PHY_INT_CLR,
priv->usbphyaddr);
return IRQ_HANDLED;
}
static int usbhs1_hardware_init(struct platform_device *pdev)
{
struct usbhs_private *priv = usbhs_get_priv(pdev);
int ret;
irq_set_irq_type(priv->irq, IRQ_TYPE_LEVEL_HIGH);
/* clear interrupt status */
__raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->usbphyaddr);
ret = request_irq(priv->irq, usbhs1_interrupt, 0,
dev_name(&pdev->dev), pdev);
if (ret) {
dev_err(&pdev->dev, "request_irq err\n");
return ret;
}
/* enable USB phy interrupt */
__raw_writew(USB_PHY_MODE | USB_PHY_INT_EN, priv->usbphyaddr);
return 0;
}
static void usbhs1_hardware_exit(struct platform_device *pdev)
{
struct usbhs_private *priv = usbhs_get_priv(pdev);
/* clear interrupt status */
__raw_writew(USB_PHY_MODE | USB_PHY_INT_CLR, priv->usbphyaddr);
free_irq(priv->irq, pdev);
}
static void usbhs1_phy_reset(struct platform_device *pdev)
{
struct usbhs_private *priv = usbhs_get_priv(pdev);
/* init phy */
__raw_writew(0x8a0a, priv->usbcrcaddr);
}
static u32 usbhs1_pipe_cfg[] = {
USB_ENDPOINT_XFER_CONTROL,
USB_ENDPOINT_XFER_ISOC,
USB_ENDPOINT_XFER_ISOC,
USB_ENDPOINT_XFER_BULK,
USB_ENDPOINT_XFER_BULK,
USB_ENDPOINT_XFER_BULK,
USB_ENDPOINT_XFER_INT,
USB_ENDPOINT_XFER_INT,
USB_ENDPOINT_XFER_INT,
USB_ENDPOINT_XFER_BULK,
USB_ENDPOINT_XFER_BULK,
USB_ENDPOINT_XFER_BULK,
USB_ENDPOINT_XFER_BULK,
USB_ENDPOINT_XFER_BULK,
USB_ENDPOINT_XFER_BULK,
USB_ENDPOINT_XFER_BULK,
};
static struct usbhs_private usbhs1_private = {
.irq = evt2irq(0x0300), /* IRQ8 */
.usbphyaddr = 0xE60581E2, /* USBPHY1INTAP */
.usbcrcaddr = 0xE6058130, /* USBCR4 */
.info = {
.platform_callback = {
.hardware_init = usbhs1_hardware_init,
.hardware_exit = usbhs1_hardware_exit,
.phy_reset = usbhs1_phy_reset,
.get_id = usbhs1_get_id,
.get_vbus = usbhs1_get_vbus,
},
.driver_param = {
.buswait_bwait = 4,
.pipe_type = usbhs1_pipe_cfg,
.pipe_size = ARRAY_SIZE(usbhs1_pipe_cfg),
},
},
};
static struct resource usbhs1_resources[] = {
[0] = {
.name = "USBHS",
.start = 0xE68B0000,
.end = 0xE68B00E6 - 1,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = evt2irq(0x1ce0) /* USB1_USB1I0 */,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device usbhs1_device = {
.name = "renesas_usbhs",
.id = 1,
.dev = {
.platform_data = &usbhs1_private.info,
},
.num_resources = ARRAY_SIZE(usbhs1_resources),
.resource = usbhs1_resources,
};
/* LED */ /* LED */
static struct gpio_led mackerel_leds[] = { static struct gpio_led mackerel_leds[] = {
{ {
...@@ -690,7 +870,15 @@ static struct resource sdhi0_resources[] = { ...@@ -690,7 +870,15 @@ static struct resource sdhi0_resources[] = {
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
}, },
[1] = { [1] = {
.start = evt2irq(0x0e00) /* SDHI0 */, .start = evt2irq(0x0e00) /* SDHI0_SDHI0I0 */,
.flags = IORESOURCE_IRQ,
},
[2] = {
.start = evt2irq(0x0e20) /* SDHI0_SDHI0I1 */,
.flags = IORESOURCE_IRQ,
},
[3] = {
.start = evt2irq(0x0e40) /* SDHI0_SDHI0I2 */,
.flags = IORESOURCE_IRQ, .flags = IORESOURCE_IRQ,
}, },
}; };
...@@ -705,7 +893,7 @@ static struct platform_device sdhi0_device = { ...@@ -705,7 +893,7 @@ static struct platform_device sdhi0_device = {
}, },
}; };
#if !defined(CONFIG_MMC_SH_MMCIF) #if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE)
/* SDHI1 */ /* SDHI1 */
static struct sh_mobile_sdhi_info sdhi1_info = { static struct sh_mobile_sdhi_info sdhi1_info = {
.dma_slave_tx = SHDMA_SLAVE_SDHI1_TX, .dma_slave_tx = SHDMA_SLAVE_SDHI1_TX,
...@@ -725,7 +913,15 @@ static struct resource sdhi1_resources[] = { ...@@ -725,7 +913,15 @@ static struct resource sdhi1_resources[] = {
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
}, },
[1] = { [1] = {
.start = evt2irq(0x0e80), .start = evt2irq(0x0e80), /* SDHI1_SDHI1I0 */
.flags = IORESOURCE_IRQ,
},
[2] = {
.start = evt2irq(0x0ea0), /* SDHI1_SDHI1I1 */
.flags = IORESOURCE_IRQ,
},
[3] = {
.start = evt2irq(0x0ec0), /* SDHI1_SDHI1I2 */
.flags = IORESOURCE_IRQ, .flags = IORESOURCE_IRQ,
}, },
}; };
...@@ -768,7 +964,15 @@ static struct resource sdhi2_resources[] = { ...@@ -768,7 +964,15 @@ static struct resource sdhi2_resources[] = {
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
}, },
[1] = { [1] = {
.start = evt2irq(0x1200), .start = evt2irq(0x1200), /* SDHI2_SDHI2I0 */
.flags = IORESOURCE_IRQ,
},
[2] = {
.start = evt2irq(0x1220), /* SDHI2_SDHI2I1 */
.flags = IORESOURCE_IRQ,
},
[3] = {
.start = evt2irq(0x1240), /* SDHI2_SDHI2I2 */
.flags = IORESOURCE_IRQ, .flags = IORESOURCE_IRQ,
}, },
}; };
...@@ -803,6 +1007,15 @@ static struct resource sh_mmcif_resources[] = { ...@@ -803,6 +1007,15 @@ static struct resource sh_mmcif_resources[] = {
}, },
}; };
static struct sh_mmcif_dma sh_mmcif_dma = {
.chan_priv_rx = {
.slave_id = SHDMA_SLAVE_MMCIF_RX,
},
.chan_priv_tx = {
.slave_id = SHDMA_SLAVE_MMCIF_TX,
},
};
static struct sh_mmcif_plat_data sh_mmcif_plat = { static struct sh_mmcif_plat_data sh_mmcif_plat = {
.sup_pclk = 0, .sup_pclk = 0,
.ocr = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34, .ocr = MMC_VDD_165_195 | MMC_VDD_32_33 | MMC_VDD_33_34,
...@@ -810,6 +1023,7 @@ static struct sh_mmcif_plat_data sh_mmcif_plat = { ...@@ -810,6 +1023,7 @@ static struct sh_mmcif_plat_data sh_mmcif_plat = {
MMC_CAP_8_BIT_DATA | MMC_CAP_8_BIT_DATA |
MMC_CAP_NEEDS_POLL, MMC_CAP_NEEDS_POLL,
.get_cd = slot_cn7_get_cd, .get_cd = slot_cn7_get_cd,
.dma = &sh_mmcif_dma,
}; };
static struct platform_device sh_mmcif_device = { static struct platform_device sh_mmcif_device = {
...@@ -858,37 +1072,23 @@ static struct soc_camera_link camera_link = { ...@@ -858,37 +1072,23 @@ static struct soc_camera_link camera_link = {
.priv = &camera_info, .priv = &camera_info,
}; };
static void dummy_release(struct device *dev) static struct platform_device *camera_device;
static void mackerel_camera_release(struct device *dev)
{ {
soc_camera_platform_release(&camera_device);
} }
static struct platform_device camera_device = {
.name = "soc_camera_platform",
.dev = {
.platform_data = &camera_info,
.release = dummy_release,
},
};
static int mackerel_camera_add(struct soc_camera_link *icl, static int mackerel_camera_add(struct soc_camera_link *icl,
struct device *dev) struct device *dev)
{ {
if (icl != &camera_link) return soc_camera_platform_add(icl, dev, &camera_device, &camera_link,
return -ENODEV; mackerel_camera_release, 0);
camera_info.dev = dev;
return platform_device_register(&camera_device);
} }
static void mackerel_camera_del(struct soc_camera_link *icl) static void mackerel_camera_del(struct soc_camera_link *icl)
{ {
if (icl != &camera_link) soc_camera_platform_del(icl, camera_device, &camera_link);
return;
platform_device_unregister(&camera_device);
memset(&camera_device.dev.kobj, 0,
sizeof(camera_device.dev.kobj));
} }
static struct sh_mobile_ceu_info sh_mobile_ceu_info = { static struct sh_mobile_ceu_info sh_mobile_ceu_info = {
...@@ -935,12 +1135,13 @@ static struct platform_device *mackerel_devices[] __initdata = { ...@@ -935,12 +1135,13 @@ static struct platform_device *mackerel_devices[] __initdata = {
&smc911x_device, &smc911x_device,
&lcdc_device, &lcdc_device,
&usb1_host_device, &usb1_host_device,
&usbhs1_device,
&leds_device, &leds_device,
&fsi_device, &fsi_device,
&fsi_ak4643_device, &fsi_ak4643_device,
&fsi_hdmi_device, &fsi_hdmi_device,
&sdhi0_device, &sdhi0_device,
#if !defined(CONFIG_MMC_SH_MMCIF) #if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE)
&sdhi1_device, &sdhi1_device,
#endif #endif
&sdhi2_device, &sdhi2_device,
...@@ -1030,6 +1231,7 @@ static void __init mackerel_map_io(void) ...@@ -1030,6 +1231,7 @@ static void __init mackerel_map_io(void)
#define GPIO_PORT9CR 0xE6051009 #define GPIO_PORT9CR 0xE6051009
#define GPIO_PORT10CR 0xE605100A #define GPIO_PORT10CR 0xE605100A
#define GPIO_PORT168CR 0xE60520A8
#define SRCR4 0xe61580bc #define SRCR4 0xe61580bc
#define USCCR1 0xE6058144 #define USCCR1 0xE6058144
static void __init mackerel_init(void) static void __init mackerel_init(void)
...@@ -1088,6 +1290,7 @@ static void __init mackerel_init(void) ...@@ -1088,6 +1290,7 @@ static void __init mackerel_init(void)
gpio_request(GPIO_FN_OVCN_1_114, NULL); gpio_request(GPIO_FN_OVCN_1_114, NULL);
gpio_request(GPIO_FN_EXTLP_1, NULL); gpio_request(GPIO_FN_EXTLP_1, NULL);
gpio_request(GPIO_FN_OVCN2_1, NULL); gpio_request(GPIO_FN_OVCN2_1, NULL);
gpio_pull_down(GPIO_PORT168CR);
/* setup USB phy */ /* setup USB phy */
__raw_writew(0x8a0a, 0xE6058130); /* USBCR4 */ __raw_writew(0x8a0a, 0xE6058130); /* USBCR4 */
...@@ -1140,7 +1343,7 @@ static void __init mackerel_init(void) ...@@ -1140,7 +1343,7 @@ static void __init mackerel_init(void)
gpio_request(GPIO_FN_SDHID0_1, NULL); gpio_request(GPIO_FN_SDHID0_1, NULL);
gpio_request(GPIO_FN_SDHID0_0, NULL); gpio_request(GPIO_FN_SDHID0_0, NULL);
#if !defined(CONFIG_MMC_SH_MMCIF) #if !defined(CONFIG_MMC_SH_MMCIF) && !defined(CONFIG_MMC_SH_MMCIF_MODULE)
/* enable SDHI1 */ /* enable SDHI1 */
gpio_request(GPIO_FN_SDHICMD1, NULL); gpio_request(GPIO_FN_SDHICMD1, NULL);
gpio_request(GPIO_FN_SDHICLK1, NULL); gpio_request(GPIO_FN_SDHICLK1, NULL);
...@@ -1216,6 +1419,7 @@ static void __init mackerel_init(void) ...@@ -1216,6 +1419,7 @@ static void __init mackerel_init(void)
platform_add_devices(mackerel_devices, ARRAY_SIZE(mackerel_devices)); platform_add_devices(mackerel_devices, ARRAY_SIZE(mackerel_devices));
hdmi_init_pm_clock(); hdmi_init_pm_clock();
sh7372_pm_init();
} }
static void __init mackerel_timer_init(void) static void __init mackerel_timer_init(void)
......
...@@ -44,6 +44,11 @@ ...@@ -44,6 +44,11 @@
#define DSI1PCKCR 0xe6150098 #define DSI1PCKCR 0xe6150098
#define PLLC01CR 0xe6150028 #define PLLC01CR 0xe6150028
#define PLLC2CR 0xe615002c #define PLLC2CR 0xe615002c
#define RMSTPCR0 0xe6150110
#define RMSTPCR1 0xe6150114
#define RMSTPCR2 0xe6150118
#define RMSTPCR3 0xe615011c
#define RMSTPCR4 0xe6150120
#define SMSTPCR0 0xe6150130 #define SMSTPCR0 0xe6150130
#define SMSTPCR1 0xe6150134 #define SMSTPCR1 0xe6150134
#define SMSTPCR2 0xe6150138 #define SMSTPCR2 0xe6150138
...@@ -421,9 +426,6 @@ static unsigned long fsidiv_recalc(struct clk *clk) ...@@ -421,9 +426,6 @@ static unsigned long fsidiv_recalc(struct clk *clk)
value = __raw_readl(clk->mapping->base); value = __raw_readl(clk->mapping->base);
if ((value & 0x3) != 0x3)
return 0;
value >>= 16; value >>= 16;
if (value < 2) if (value < 2)
return 0; return 0;
...@@ -504,7 +506,7 @@ static struct clk *late_main_clks[] = { ...@@ -504,7 +506,7 @@ static struct clk *late_main_clks[] = {
enum { MSTP001, enum { MSTP001,
MSTP131, MSTP130, MSTP131, MSTP130,
MSTP129, MSTP128, MSTP127, MSTP126, MSTP125, MSTP129, MSTP128, MSTP127, MSTP126, MSTP125,
MSTP118, MSTP117, MSTP116, MSTP118, MSTP117, MSTP116, MSTP113,
MSTP106, MSTP101, MSTP100, MSTP106, MSTP101, MSTP100,
MSTP223, MSTP223,
MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
...@@ -527,6 +529,7 @@ static struct clk mstp_clks[MSTP_NR] = { ...@@ -527,6 +529,7 @@ static struct clk mstp_clks[MSTP_NR] = {
[MSTP118] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 18, 0), /* DSITX */ [MSTP118] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 18, 0), /* DSITX */
[MSTP117] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 17, 0), /* LCDC1 */ [MSTP117] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 17, 0), /* LCDC1 */
[MSTP116] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR1, 16, 0), /* IIC0 */ [MSTP116] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR1, 16, 0), /* IIC0 */
[MSTP113] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR1, 13, 0), /* MERAM */
[MSTP106] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 6, 0), /* JPU */ [MSTP106] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 6, 0), /* JPU */
[MSTP101] = MSTP(&div4_clks[DIV4_M1], SMSTPCR1, 1, 0), /* VPU */ [MSTP101] = MSTP(&div4_clks[DIV4_M1], SMSTPCR1, 1, 0), /* VPU */
[MSTP100] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 0, 0), /* LCDC0 */ [MSTP100] = MSTP(&div4_clks[DIV4_B], SMSTPCR1, 0, 0), /* LCDC0 */
...@@ -617,6 +620,7 @@ static struct clk_lookup lookups[] = { ...@@ -617,6 +620,7 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("sh-mipi-dsi.0", &mstp_clks[MSTP118]), /* DSITX0 */ CLKDEV_DEV_ID("sh-mipi-dsi.0", &mstp_clks[MSTP118]), /* DSITX0 */
CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1", &mstp_clks[MSTP117]), /* LCDC1 */ CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1", &mstp_clks[MSTP117]), /* LCDC1 */
CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* IIC0 */ CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* IIC0 */
CLKDEV_DEV_ID("sh_mobile_meram.0", &mstp_clks[MSTP113]), /* MERAM */
CLKDEV_DEV_ID("uio_pdrv_genirq.5", &mstp_clks[MSTP106]), /* JPU */ CLKDEV_DEV_ID("uio_pdrv_genirq.5", &mstp_clks[MSTP106]), /* JPU */
CLKDEV_DEV_ID("uio_pdrv_genirq.0", &mstp_clks[MSTP101]), /* VPU */ CLKDEV_DEV_ID("uio_pdrv_genirq.0", &mstp_clks[MSTP101]), /* VPU */
CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[MSTP100]), /* LCDC0 */ CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[MSTP100]), /* LCDC0 */
...@@ -634,6 +638,7 @@ static struct clk_lookup lookups[] = { ...@@ -634,6 +638,7 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */ CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */
CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP322]), /* USB0 */ CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP322]), /* USB0 */
CLKDEV_DEV_ID("r8a66597_udc.0", &mstp_clks[MSTP322]), /* USB0 */ CLKDEV_DEV_ID("r8a66597_udc.0", &mstp_clks[MSTP322]), /* USB0 */
CLKDEV_DEV_ID("renesas_usbhs.0", &mstp_clks[MSTP322]), /* USB0 */
CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */ CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */
CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */ CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */
CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMC */ CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMC */
...@@ -644,6 +649,7 @@ static struct clk_lookup lookups[] = { ...@@ -644,6 +649,7 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("i2c-sh_mobile.4", &mstp_clks[MSTP410]), /* IIC4 */ CLKDEV_DEV_ID("i2c-sh_mobile.4", &mstp_clks[MSTP410]), /* IIC4 */
CLKDEV_DEV_ID("r8a66597_hcd.1", &mstp_clks[MSTP406]), /* USB1 */ CLKDEV_DEV_ID("r8a66597_hcd.1", &mstp_clks[MSTP406]), /* USB1 */
CLKDEV_DEV_ID("r8a66597_udc.1", &mstp_clks[MSTP406]), /* USB1 */ CLKDEV_DEV_ID("r8a66597_udc.1", &mstp_clks[MSTP406]), /* USB1 */
CLKDEV_DEV_ID("renesas_usbhs.1", &mstp_clks[MSTP406]), /* USB1 */
CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */ CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */
CLKDEV_ICK_ID("ick", "sh-mobile-hdmi", &div6_reparent_clks[DIV6_HDMI]), CLKDEV_ICK_ID("ick", "sh-mobile-hdmi", &div6_reparent_clks[DIV6_HDMI]),
...@@ -655,6 +661,13 @@ void __init sh7372_clock_init(void) ...@@ -655,6 +661,13 @@ void __init sh7372_clock_init(void)
{ {
int k, ret = 0; int k, ret = 0;
/* make sure MSTP bits on the RT/SH4AL-DSP side are off */
__raw_writel(0xe4ef8087, RMSTPCR0);
__raw_writel(0xffffffff, RMSTPCR1);
__raw_writel(0x37c7f7ff, RMSTPCR2);
__raw_writel(0xffffffff, RMSTPCR3);
__raw_writel(0xffe0fffd, RMSTPCR4);
for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++) for (k = 0; !ret && (k < ARRAY_SIZE(main_clks)); k++)
ret = clk_register(main_clks[k]); ret = clk_register(main_clks[k]);
......
...@@ -266,7 +266,8 @@ enum { MSTP001, ...@@ -266,7 +266,8 @@ enum { MSTP001,
MSTP129, MSTP128, MSTP127, MSTP126, MSTP125, MSTP118, MSTP116, MSTP100, MSTP129, MSTP128, MSTP127, MSTP126, MSTP125, MSTP118, MSTP116, MSTP100,
MSTP219, MSTP219,
MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200, MSTP207, MSTP206, MSTP204, MSTP203, MSTP202, MSTP201, MSTP200,
MSTP331, MSTP329, MSTP325, MSTP323, MSTP312, MSTP331, MSTP329, MSTP325, MSTP323, MSTP318,
MSTP314, MSTP313, MSTP312, MSTP311,
MSTP411, MSTP410, MSTP403, MSTP411, MSTP410, MSTP403,
MSTP_NR }; MSTP_NR };
...@@ -295,7 +296,11 @@ static struct clk mstp_clks[MSTP_NR] = { ...@@ -295,7 +296,11 @@ static struct clk mstp_clks[MSTP_NR] = {
[MSTP329] = MSTP(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */ [MSTP329] = MSTP(&r_clk, SMSTPCR3, 29, 0), /* CMT10 */
[MSTP325] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 25, 0), /* IrDA */ [MSTP325] = MSTP(&div6_clks[DIV6_SUB], SMSTPCR3, 25, 0), /* IrDA */
[MSTP323] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 23, 0), /* IIC1 */ [MSTP323] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 23, 0), /* IIC1 */
[MSTP318] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 18, 0), /* SY-DMAC */
[MSTP314] = MSTP(&div6_clks[DIV6_SDHI0], SMSTPCR3, 14, 0), /* SDHI0 */
[MSTP313] = MSTP(&div6_clks[DIV6_SDHI1], SMSTPCR3, 13, 0), /* SDHI1 */
[MSTP312] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMCIF0 */ [MSTP312] = MSTP(&div4_clks[DIV4_HP], SMSTPCR3, 12, 0), /* MMCIF0 */
[MSTP311] = MSTP(&div6_clks[DIV6_SDHI2], SMSTPCR3, 11, 0), /* SDHI2 */
[MSTP411] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 11, 0), /* IIC3 */ [MSTP411] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 11, 0), /* IIC3 */
[MSTP410] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 10, 0), /* IIC4 */ [MSTP410] = MSTP(&div4_clks[DIV4_HP], SMSTPCR4, 10, 0), /* IIC4 */
[MSTP403] = MSTP(&r_clk, SMSTPCR4, 3, 0), /* KEYSC */ [MSTP403] = MSTP(&r_clk, SMSTPCR4, 3, 0), /* KEYSC */
...@@ -313,6 +318,9 @@ static struct clk_lookup lookups[] = { ...@@ -313,6 +318,9 @@ static struct clk_lookup lookups[] = {
CLKDEV_CON_ID("vck1_clk", &div6_clks[DIV6_VCK1]), CLKDEV_CON_ID("vck1_clk", &div6_clks[DIV6_VCK1]),
CLKDEV_CON_ID("vck2_clk", &div6_clks[DIV6_VCK2]), CLKDEV_CON_ID("vck2_clk", &div6_clks[DIV6_VCK2]),
CLKDEV_CON_ID("vck3_clk", &div6_clks[DIV6_VCK3]), CLKDEV_CON_ID("vck3_clk", &div6_clks[DIV6_VCK3]),
CLKDEV_CON_ID("sdhi0_clk", &div6_clks[DIV6_SDHI0]),
CLKDEV_CON_ID("sdhi1_clk", &div6_clks[DIV6_SDHI1]),
CLKDEV_CON_ID("sdhi2_clk", &div6_clks[DIV6_SDHI2]),
CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]), CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSIT]),
CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSIT]), CLKDEV_ICK_ID("dsit_clk", "sh-mipi-dsi.1", &div6_clks[DIV6_DSIT]),
CLKDEV_ICK_ID("dsi0p_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]), CLKDEV_ICK_ID("dsi0p_clk", "sh-mipi-dsi.0", &div6_clks[DIV6_DSI0P]),
...@@ -341,7 +349,11 @@ static struct clk_lookup lookups[] = { ...@@ -341,7 +349,11 @@ static struct clk_lookup lookups[] = {
CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), /* CMT10 */ CLKDEV_DEV_ID("sh_cmt.10", &mstp_clks[MSTP329]), /* CMT10 */
CLKDEV_DEV_ID("sh_irda.0", &mstp_clks[MSTP325]), /* IrDA */ CLKDEV_DEV_ID("sh_irda.0", &mstp_clks[MSTP325]), /* IrDA */
CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* I2C1 */ CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* I2C1 */
CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP318]), /* SY-DMAC */
CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */
CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */
CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMCIF0 */ CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMCIF0 */
CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP311]), /* SDHI2 */
CLKDEV_DEV_ID("i2c-sh_mobile.3", &mstp_clks[MSTP411]), /* I2C3 */ CLKDEV_DEV_ID("i2c-sh_mobile.3", &mstp_clks[MSTP411]), /* I2C3 */
CLKDEV_DEV_ID("i2c-sh_mobile.4", &mstp_clks[MSTP410]), /* I2C4 */ CLKDEV_DEV_ID("i2c-sh_mobile.4", &mstp_clks[MSTP410]), /* I2C4 */
CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */ CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */
...@@ -351,6 +363,11 @@ void __init sh73a0_clock_init(void) ...@@ -351,6 +363,11 @@ void __init sh73a0_clock_init(void)
{ {
int k, ret = 0; int k, ret = 0;
/* Set SDHI clocks to a known state */
__raw_writel(0x108, SD0CKCR);
__raw_writel(0x108, SD1CKCR);
__raw_writel(0x108, SD2CKCR);
/* detect main clock parent */ /* detect main clock parent */
switch ((__raw_readl(CKSCR) >> 24) & 0x03) { switch ((__raw_readl(CKSCR) >> 24) & 0x03) {
case 0: case 0:
......
/*
* CPUIdle support code for SH-Mobile ARM
*
* Copyright (C) 2011 Magnus Damm
*
* 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.
*/
#include <linux/pm.h>
#include <linux/cpuidle.h>
#include <linux/suspend.h>
#include <linux/module.h>
#include <linux/err.h>
#include <asm/system.h>
#include <asm/io.h>
static void shmobile_enter_wfi(void)
{
cpu_do_idle();
}
void (*shmobile_cpuidle_modes[CPUIDLE_STATE_MAX])(void) = {
shmobile_enter_wfi, /* regular sleep mode */
};
static int shmobile_cpuidle_enter(struct cpuidle_device *dev,
struct cpuidle_state *state)
{
ktime_t before, after;
int requested_state = state - &dev->states[0];
dev->last_state = &dev->states[requested_state];
before = ktime_get();
local_irq_disable();
local_fiq_disable();
shmobile_cpuidle_modes[requested_state]();
local_irq_enable();
local_fiq_enable();
after = ktime_get();
return ktime_to_ns(ktime_sub(after, before)) >> 10;
}
static struct cpuidle_device shmobile_cpuidle_dev;
static struct cpuidle_driver shmobile_cpuidle_driver = {
.name = "shmobile_cpuidle",
.owner = THIS_MODULE,
};
void (*shmobile_cpuidle_setup)(struct cpuidle_device *dev);
static int shmobile_cpuidle_init(void)
{
struct cpuidle_device *dev = &shmobile_cpuidle_dev;
struct cpuidle_state *state;
int i;
cpuidle_register_driver(&shmobile_cpuidle_driver);
for (i = 0; i < CPUIDLE_STATE_MAX; i++) {
dev->states[i].name[0] = '\0';
dev->states[i].desc[0] = '\0';
dev->states[i].enter = shmobile_cpuidle_enter;
}
i = CPUIDLE_DRIVER_STATE_START;
state = &dev->states[i++];
snprintf(state->name, CPUIDLE_NAME_LEN, "C1");
strncpy(state->desc, "WFI", CPUIDLE_DESC_LEN);
state->exit_latency = 1;
state->target_residency = 1 * 2;
state->power_usage = 3;
state->flags = 0;
state->flags |= CPUIDLE_FLAG_TIME_VALID;
dev->safe_state = state;
dev->state_count = i;
if (shmobile_cpuidle_setup)
shmobile_cpuidle_setup(dev);
cpuidle_register_device(dev);
return 0;
}
late_initcall(shmobile_cpuidle_init);
...@@ -24,4 +24,4 @@ ...@@ -24,4 +24,4 @@
.align 12 .align 12
ENTRY(shmobile_secondary_vector) ENTRY(shmobile_secondary_vector)
ldr pc, 1f ldr pc, 1f
1: .long secondary_startup - PAGE_OFFSET + PHYS_OFFSET 1: .long secondary_startup - PAGE_OFFSET + PLAT_PHYS_OFFSET
...@@ -8,6 +8,10 @@ struct clk; ...@@ -8,6 +8,10 @@ struct clk;
extern int clk_init(void); extern int clk_init(void);
extern void shmobile_handle_irq_intc(struct pt_regs *); extern void shmobile_handle_irq_intc(struct pt_regs *);
extern void shmobile_handle_irq_gic(struct pt_regs *); extern void shmobile_handle_irq_gic(struct pt_regs *);
extern struct platform_suspend_ops shmobile_suspend_ops;
struct cpuidle_device;
extern void (*shmobile_cpuidle_modes[])(void);
extern void (*shmobile_cpuidle_setup)(struct cpuidle_device *dev);
extern void sh7367_init_irq(void); extern void sh7367_init_irq(void);
extern void sh7367_add_early_devices(void); extern void sh7367_add_early_devices(void);
...@@ -30,6 +34,9 @@ extern void sh7372_add_early_devices(void); ...@@ -30,6 +34,9 @@ extern void sh7372_add_early_devices(void);
extern void sh7372_add_standard_devices(void); extern void sh7372_add_standard_devices(void);
extern void sh7372_clock_init(void); extern void sh7372_clock_init(void);
extern void sh7372_pinmux_init(void); extern void sh7372_pinmux_init(void);
extern void sh7372_pm_init(void);
extern void sh7372_cpu_suspend(void);
extern void sh7372_cpu_resume(void);
extern struct clk sh7372_extal1_clk; extern struct clk sh7372_extal1_clk;
extern struct clk sh7372_extal2_clk; extern struct clk sh7372_extal2_clk;
......
...@@ -87,8 +87,7 @@ WAIT 1, 0xFE40009C ...@@ -87,8 +87,7 @@ WAIT 1, 0xFE40009C
ED 0xFE400354, 0x01AD8002 ED 0xFE400354, 0x01AD8002
LIST "SCIF0 - Serial port for earlyprintk" LIST "SCIF0 - Serial port for earlyprintk"
EB 0xE6053098, 0x11
EB 0xE6053098, 0xe1 EB 0xE6053098, 0xe1
EW 0xE6C40000, 0x0000 EW 0xE6C40000, 0x0000
EB 0xE6C40004, 0x19 EB 0xE6C40004, 0x19
EW 0xE6C40008, 0x3000 EW 0xE6C40008, 0x0030
...@@ -87,8 +87,7 @@ WAIT 1, 0xFE40009C ...@@ -87,8 +87,7 @@ WAIT 1, 0xFE40009C
ED 0xFE400354, 0x01AD8002 ED 0xFE400354, 0x01AD8002
LIST "SCIF0 - Serial port for earlyprintk" LIST "SCIF0 - Serial port for earlyprintk"
EB 0xE6053098, 0x11
EB 0xE6053098, 0xe1 EB 0xE6053098, 0xe1
EW 0xE6C40000, 0x0000 EW 0xE6C40000, 0x0000
EB 0xE6C40004, 0x19 EB 0xE6C40004, 0x19
EW 0xE6C40008, 0x3000 EW 0xE6C40008, 0x0030
...@@ -435,6 +435,7 @@ enum { ...@@ -435,6 +435,7 @@ enum {
/* DMA slave IDs */ /* DMA slave IDs */
enum { enum {
SHDMA_SLAVE_INVALID,
SHDMA_SLAVE_SCIF0_TX, SHDMA_SLAVE_SCIF0_TX,
SHDMA_SLAVE_SCIF0_RX, SHDMA_SLAVE_SCIF0_RX,
SHDMA_SLAVE_SCIF1_TX, SHDMA_SLAVE_SCIF1_TX,
......
...@@ -463,5 +463,35 @@ enum { ...@@ -463,5 +463,35 @@ enum {
GPIO_FN_FSIAIBT_PU, GPIO_FN_FSIAIBT_PU,
GPIO_FN_FSIAISLD_PU, GPIO_FN_FSIAISLD_PU,
}; };
/* DMA slave IDs */
enum {
SHDMA_SLAVE_INVALID,
SHDMA_SLAVE_SCIF0_TX,
SHDMA_SLAVE_SCIF0_RX,
SHDMA_SLAVE_SCIF1_TX,
SHDMA_SLAVE_SCIF1_RX,
SHDMA_SLAVE_SCIF2_TX,
SHDMA_SLAVE_SCIF2_RX,
SHDMA_SLAVE_SCIF3_TX,
SHDMA_SLAVE_SCIF3_RX,
SHDMA_SLAVE_SCIF4_TX,
SHDMA_SLAVE_SCIF4_RX,
SHDMA_SLAVE_SCIF5_TX,
SHDMA_SLAVE_SCIF5_RX,
SHDMA_SLAVE_SCIF6_TX,
SHDMA_SLAVE_SCIF6_RX,
SHDMA_SLAVE_SCIF7_TX,
SHDMA_SLAVE_SCIF7_RX,
SHDMA_SLAVE_SCIF8_TX,
SHDMA_SLAVE_SCIF8_RX,
SHDMA_SLAVE_SDHI0_TX,
SHDMA_SLAVE_SDHI0_RX,
SHDMA_SLAVE_SDHI1_TX,
SHDMA_SLAVE_SDHI1_RX,
SHDMA_SLAVE_SDHI2_TX,
SHDMA_SLAVE_SDHI2_RX,
SHDMA_SLAVE_MMCIF_TX,
SHDMA_SLAVE_MMCIF_RX,
};
#endif /* __ASM_SH73A0_H__ */ #endif /* __ASM_SH73A0_H__ */
...@@ -27,8 +27,6 @@ ...@@ -27,8 +27,6 @@
enum { enum {
UNUSED_INTCA = 0, UNUSED_INTCA = 0,
ENABLED,
DISABLED,
/* interrupt sources INTCA */ /* interrupt sources INTCA */
IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A, IRQ0A, IRQ1A, IRQ2A, IRQ3A, IRQ4A, IRQ5A, IRQ6A, IRQ7A,
...@@ -49,14 +47,14 @@ enum { ...@@ -49,14 +47,14 @@ enum {
MSIOF2, MSIOF1, MSIOF2, MSIOF1,
SCIFA4, SCIFA5, SCIFB, SCIFA4, SCIFA5, SCIFB,
FLCTL_FLSTEI, FLCTL_FLTENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I, FLCTL_FLSTEI, FLCTL_FLTENDI, FLCTL_FLTREQ0I, FLCTL_FLTREQ1I,
SDHI0, SDHI0_SDHI0I0, SDHI0_SDHI0I1, SDHI0_SDHI0I2, SDHI0_SDHI0I3,
SDHI1, SDHI1_SDHI1I0, SDHI1_SDHI1I1, SDHI1_SDHI1I2,
IRREM, IRREM,
IRDA, IRDA,
TPU0, TPU0,
TTI20, TTI20,
DDM, DDM,
SDHI2, SDHI2_SDHI2I0, SDHI2_SDHI2I1, SDHI2_SDHI2I2, SDHI2_SDHI2I3,
RWDT0, RWDT0,
DMAC1_1_DEI0, DMAC1_1_DEI1, DMAC1_1_DEI2, DMAC1_1_DEI3, DMAC1_1_DEI0, DMAC1_1_DEI1, DMAC1_1_DEI2, DMAC1_1_DEI3,
DMAC1_2_DEI4, DMAC1_2_DEI5, DMAC1_2_DADERR, DMAC1_2_DEI4, DMAC1_2_DEI5, DMAC1_2_DADERR,
...@@ -84,7 +82,7 @@ enum { ...@@ -84,7 +82,7 @@ enum {
/* interrupt groups INTCA */ /* interrupt groups INTCA */
DMAC1_1, DMAC1_2, DMAC2_1, DMAC2_2, DMAC3_1, DMAC3_2, SHWYSTAT, DMAC1_1, DMAC1_2, DMAC2_1, DMAC2_2, DMAC3_1, DMAC3_2, SHWYSTAT,
AP_ARM1, AP_ARM2, SPU2, FLCTL, IIC1 AP_ARM1, AP_ARM2, SPU2, FLCTL, IIC1, SDHI0, SDHI1, SDHI2
}; };
static struct intc_vect intca_vectors[] __initdata = { static struct intc_vect intca_vectors[] __initdata = {
...@@ -125,17 +123,17 @@ static struct intc_vect intca_vectors[] __initdata = { ...@@ -125,17 +123,17 @@ static struct intc_vect intca_vectors[] __initdata = {
INTC_VECT(SCIFB, 0x0d60), INTC_VECT(SCIFB, 0x0d60),
INTC_VECT(FLCTL_FLSTEI, 0x0d80), INTC_VECT(FLCTL_FLTENDI, 0x0da0), INTC_VECT(FLCTL_FLSTEI, 0x0d80), INTC_VECT(FLCTL_FLTENDI, 0x0da0),
INTC_VECT(FLCTL_FLTREQ0I, 0x0dc0), INTC_VECT(FLCTL_FLTREQ1I, 0x0de0), INTC_VECT(FLCTL_FLTREQ0I, 0x0dc0), INTC_VECT(FLCTL_FLTREQ1I, 0x0de0),
INTC_VECT(SDHI0, 0x0e00), INTC_VECT(SDHI0, 0x0e20), INTC_VECT(SDHI0_SDHI0I0, 0x0e00), INTC_VECT(SDHI0_SDHI0I1, 0x0e20),
INTC_VECT(SDHI0, 0x0e40), INTC_VECT(SDHI0, 0x0e60), INTC_VECT(SDHI0_SDHI0I2, 0x0e40), INTC_VECT(SDHI0_SDHI0I3, 0x0e60),
INTC_VECT(SDHI1, 0x0e80), INTC_VECT(SDHI1, 0x0ea0), INTC_VECT(SDHI1_SDHI1I0, 0x0e80), INTC_VECT(SDHI1_SDHI1I1, 0x0ea0),
INTC_VECT(SDHI1, 0x0ec0), INTC_VECT(SDHI1_SDHI1I2, 0x0ec0),
INTC_VECT(IRREM, 0x0f60), INTC_VECT(IRREM, 0x0f60),
INTC_VECT(IRDA, 0x0480), INTC_VECT(IRDA, 0x0480),
INTC_VECT(TPU0, 0x04a0), INTC_VECT(TPU0, 0x04a0),
INTC_VECT(TTI20, 0x1100), INTC_VECT(TTI20, 0x1100),
INTC_VECT(DDM, 0x1140), INTC_VECT(DDM, 0x1140),
INTC_VECT(SDHI2, 0x1200), INTC_VECT(SDHI2, 0x1220), INTC_VECT(SDHI2_SDHI2I0, 0x1200), INTC_VECT(SDHI2_SDHI2I1, 0x1220),
INTC_VECT(SDHI2, 0x1240), INTC_VECT(SDHI2, 0x1260), INTC_VECT(SDHI2_SDHI2I2, 0x1240), INTC_VECT(SDHI2_SDHI2I3, 0x1260),
INTC_VECT(RWDT0, 0x1280), INTC_VECT(RWDT0, 0x1280),
INTC_VECT(DMAC1_1_DEI0, 0x2000), INTC_VECT(DMAC1_1_DEI1, 0x2020), INTC_VECT(DMAC1_1_DEI0, 0x2000), INTC_VECT(DMAC1_1_DEI1, 0x2020),
INTC_VECT(DMAC1_1_DEI2, 0x2040), INTC_VECT(DMAC1_1_DEI3, 0x2060), INTC_VECT(DMAC1_1_DEI2, 0x2040), INTC_VECT(DMAC1_1_DEI3, 0x2060),
...@@ -195,6 +193,12 @@ static struct intc_group intca_groups[] __initdata = { ...@@ -195,6 +193,12 @@ static struct intc_group intca_groups[] __initdata = {
INTC_GROUP(FLCTL, FLCTL_FLSTEI, FLCTL_FLTENDI, INTC_GROUP(FLCTL, FLCTL_FLSTEI, FLCTL_FLTENDI,
FLCTL_FLTREQ0I, FLCTL_FLTREQ1I), FLCTL_FLTREQ0I, FLCTL_FLTREQ1I),
INTC_GROUP(IIC1, IIC1_ALI1, IIC1_TACKI1, IIC1_WAITI1, IIC1_DTEI1), INTC_GROUP(IIC1, IIC1_ALI1, IIC1_TACKI1, IIC1_WAITI1, IIC1_DTEI1),
INTC_GROUP(SDHI0, SDHI0_SDHI0I0, SDHI0_SDHI0I1,
SDHI0_SDHI0I2, SDHI0_SDHI0I3),
INTC_GROUP(SDHI1, SDHI1_SDHI1I0, SDHI1_SDHI1I1,
SDHI1_SDHI1I2),
INTC_GROUP(SDHI2, SDHI2_SDHI2I0, SDHI2_SDHI2I1,
SDHI2_SDHI2I2, SDHI2_SDHI2I3),
INTC_GROUP(SHWYSTAT, SHWYSTAT_RT, SHWYSTAT_HS, SHWYSTAT_COM), INTC_GROUP(SHWYSTAT, SHWYSTAT_RT, SHWYSTAT_HS, SHWYSTAT_COM),
}; };
...@@ -230,10 +234,10 @@ static struct intc_mask_reg intca_mask_registers[] __initdata = { ...@@ -230,10 +234,10 @@ static struct intc_mask_reg intca_mask_registers[] __initdata = {
{ SCIFB, SCIFA5, SCIFA4, MSIOF1, { SCIFB, SCIFA5, SCIFA4, MSIOF1,
0, 0, MSIOF2, 0 } }, 0, 0, MSIOF2, 0 } },
{ 0xe694009c, 0xe69400dc, 8, /* IMR7A / IMCR7A */ { 0xe694009c, 0xe69400dc, 8, /* IMR7A / IMCR7A */
{ DISABLED, ENABLED, ENABLED, ENABLED, { SDHI0_SDHI0I3, SDHI0_SDHI0I2, SDHI0_SDHI0I1, SDHI0_SDHI0I0,
FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLTENDI, FLCTL_FLSTEI } }, FLCTL_FLTREQ1I, FLCTL_FLTREQ0I, FLCTL_FLTENDI, FLCTL_FLSTEI } },
{ 0xe69400a0, 0xe69400e0, 8, /* IMR8A / IMCR8A */ { 0xe69400a0, 0xe69400e0, 8, /* IMR8A / IMCR8A */
{ 0, ENABLED, ENABLED, ENABLED, { 0, SDHI1_SDHI1I2, SDHI1_SDHI1I1, SDHI1_SDHI1I0,
TTI20, USBHSDMAC0_USHDMI, 0, 0 } }, TTI20, USBHSDMAC0_USHDMI, 0, 0 } },
{ 0xe69400a4, 0xe69400e4, 8, /* IMR9A / IMCR9A */ { 0xe69400a4, 0xe69400e4, 8, /* IMR9A / IMCR9A */
{ CMT1_CMT13, CMT1_CMT12, CMT1_CMT11, CMT1_CMT10, { CMT1_CMT13, CMT1_CMT12, CMT1_CMT11, CMT1_CMT10,
...@@ -248,7 +252,7 @@ static struct intc_mask_reg intca_mask_registers[] __initdata = { ...@@ -248,7 +252,7 @@ static struct intc_mask_reg intca_mask_registers[] __initdata = {
{ 0, 0, TPU0, 0, { 0, 0, TPU0, 0,
0, 0, 0, 0 } }, 0, 0, 0, 0 } },
{ 0xe69400b4, 0xe69400f4, 8, /* IMR13A / IMCR13A */ { 0xe69400b4, 0xe69400f4, 8, /* IMR13A / IMCR13A */
{ DISABLED, DISABLED, ENABLED, ENABLED, { SDHI2_SDHI2I3, SDHI2_SDHI2I2, SDHI2_SDHI2I1, SDHI2_SDHI2I0,
0, CMT3, 0, RWDT0 } }, 0, CMT3, 0, RWDT0 } },
{ 0xe6950080, 0xe69500c0, 8, /* IMR0A3 / IMCR0A3 */ { 0xe6950080, 0xe69500c0, 8, /* IMR0A3 / IMCR0A3 */
{ SHWYSTAT_RT, SHWYSTAT_HS, SHWYSTAT_COM, 0, { SHWYSTAT_RT, SHWYSTAT_HS, SHWYSTAT_COM, 0,
...@@ -354,14 +358,10 @@ static struct intc_mask_reg intca_ack_registers[] __initdata = { ...@@ -354,14 +358,10 @@ static struct intc_mask_reg intca_ack_registers[] __initdata = {
{ IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A } }, { IRQ24A, IRQ25A, IRQ26A, IRQ27A, IRQ28A, IRQ29A, IRQ30A, IRQ31A } },
}; };
static struct intc_desc intca_desc __initdata = { static DECLARE_INTC_DESC_ACK(intca_desc, "sh7372-intca",
.name = "sh7372-intca", intca_vectors, intca_groups,
.force_enable = ENABLED,
.force_disable = DISABLED,
.hw = INTC_HW_DESC(intca_vectors, intca_groups,
intca_mask_registers, intca_prio_registers, intca_mask_registers, intca_prio_registers,
intca_sense_registers, intca_ack_registers), intca_sense_registers, intca_ack_registers);
};
enum { enum {
UNUSED_INTCS = 0, UNUSED_INTCS = 0,
......
/*
* sh7372 Power management support
*
* Copyright (C) 2011 Magnus Damm
*
* 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.
*/
#include <linux/pm.h>
#include <linux/suspend.h>
#include <linux/cpuidle.h>
#include <linux/module.h>
#include <linux/list.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <asm/system.h>
#include <asm/io.h>
#include <asm/tlbflush.h>
#include <mach/common.h>
#define SMFRAM 0xe6a70000
#define SYSTBCR 0xe6150024
#define SBAR 0xe6180020
#define APARMBAREA 0xe6f10020
static void sh7372_enter_core_standby(void)
{
void __iomem *smfram = (void __iomem *)SMFRAM;
__raw_writel(0, APARMBAREA); /* translate 4k */
__raw_writel(__pa(sh7372_cpu_resume), SBAR); /* set reset vector */
__raw_writel(0x10, SYSTBCR); /* enable core standby */
__raw_writel(0, smfram + 0x3c); /* clear page table address */
sh7372_cpu_suspend();
cpu_init();
/* if page table address is non-NULL then we have been powered down */
if (__raw_readl(smfram + 0x3c)) {
__raw_writel(__raw_readl(smfram + 0x40),
__va(__raw_readl(smfram + 0x3c)));
flush_tlb_all();
set_cr(__raw_readl(smfram + 0x38));
}
__raw_writel(0, SYSTBCR); /* disable core standby */
__raw_writel(0, SBAR); /* disable reset vector translation */
}
#ifdef CONFIG_CPU_IDLE
static void sh7372_cpuidle_setup(struct cpuidle_device *dev)
{
struct cpuidle_state *state;
int i = dev->state_count;
state = &dev->states[i];
snprintf(state->name, CPUIDLE_NAME_LEN, "C2");
strncpy(state->desc, "Core Standby Mode", CPUIDLE_DESC_LEN);
state->exit_latency = 10;
state->target_residency = 20 + 10;
state->power_usage = 1; /* perhaps not */
state->flags = 0;
state->flags |= CPUIDLE_FLAG_TIME_VALID;
shmobile_cpuidle_modes[i] = sh7372_enter_core_standby;
dev->state_count = i + 1;
}
static void sh7372_cpuidle_init(void)
{
shmobile_cpuidle_setup = sh7372_cpuidle_setup;
}
#else
static void sh7372_cpuidle_init(void) {}
#endif
#ifdef CONFIG_SUSPEND
static int sh7372_enter_suspend(suspend_state_t suspend_state)
{
sh7372_enter_core_standby();
return 0;
}
static void sh7372_suspend_init(void)
{
shmobile_suspend_ops.enter = sh7372_enter_suspend;
}
#else
static void sh7372_suspend_init(void) {}
#endif
#define DBGREG1 0xe6100020
#define DBGREG9 0xe6100040
void __init sh7372_pm_init(void)
{
/* enable DBG hardware block to kick SYSC */
__raw_writel(0x0000a500, DBGREG9);
__raw_writel(0x0000a501, DBGREG9);
__raw_writel(0x00000000, DBGREG1);
sh7372_suspend_init();
sh7372_cpuidle_init();
}
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/uio_driver.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/io.h> #include <linux/io.h>
...@@ -195,6 +196,214 @@ static struct platform_device cmt10_device = { ...@@ -195,6 +196,214 @@ static struct platform_device cmt10_device = {
.num_resources = ARRAY_SIZE(cmt10_resources), .num_resources = ARRAY_SIZE(cmt10_resources),
}; };
/* VPU */
static struct uio_info vpu_platform_data = {
.name = "VPU5",
.version = "0",
.irq = intcs_evt2irq(0x980),
};
static struct resource vpu_resources[] = {
[0] = {
.name = "VPU",
.start = 0xfe900000,
.end = 0xfe902807,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device vpu_device = {
.name = "uio_pdrv_genirq",
.id = 0,
.dev = {
.platform_data = &vpu_platform_data,
},
.resource = vpu_resources,
.num_resources = ARRAY_SIZE(vpu_resources),
};
/* VEU0 */
static struct uio_info veu0_platform_data = {
.name = "VEU0",
.version = "0",
.irq = intcs_evt2irq(0x700),
};
static struct resource veu0_resources[] = {
[0] = {
.name = "VEU0",
.start = 0xfe920000,
.end = 0xfe9200b7,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device veu0_device = {
.name = "uio_pdrv_genirq",
.id = 1,
.dev = {
.platform_data = &veu0_platform_data,
},
.resource = veu0_resources,
.num_resources = ARRAY_SIZE(veu0_resources),
};
/* VEU1 */
static struct uio_info veu1_platform_data = {
.name = "VEU1",
.version = "0",
.irq = intcs_evt2irq(0x720),
};
static struct resource veu1_resources[] = {
[0] = {
.name = "VEU1",
.start = 0xfe924000,
.end = 0xfe9240b7,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device veu1_device = {
.name = "uio_pdrv_genirq",
.id = 2,
.dev = {
.platform_data = &veu1_platform_data,
},
.resource = veu1_resources,
.num_resources = ARRAY_SIZE(veu1_resources),
};
/* VEU2 */
static struct uio_info veu2_platform_data = {
.name = "VEU2",
.version = "0",
.irq = intcs_evt2irq(0x740),
};
static struct resource veu2_resources[] = {
[0] = {
.name = "VEU2",
.start = 0xfe928000,
.end = 0xfe9280b7,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device veu2_device = {
.name = "uio_pdrv_genirq",
.id = 3,
.dev = {
.platform_data = &veu2_platform_data,
},
.resource = veu2_resources,
.num_resources = ARRAY_SIZE(veu2_resources),
};
/* VEU3 */
static struct uio_info veu3_platform_data = {
.name = "VEU3",
.version = "0",
.irq = intcs_evt2irq(0x760),
};
static struct resource veu3_resources[] = {
[0] = {
.name = "VEU3",
.start = 0xfe92c000,
.end = 0xfe92c0b7,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device veu3_device = {
.name = "uio_pdrv_genirq",
.id = 4,
.dev = {
.platform_data = &veu3_platform_data,
},
.resource = veu3_resources,
.num_resources = ARRAY_SIZE(veu3_resources),
};
/* VEU2H */
static struct uio_info veu2h_platform_data = {
.name = "VEU2H",
.version = "0",
.irq = intcs_evt2irq(0x520),
};
static struct resource veu2h_resources[] = {
[0] = {
.name = "VEU2H",
.start = 0xfe93c000,
.end = 0xfe93c27b,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device veu2h_device = {
.name = "uio_pdrv_genirq",
.id = 5,
.dev = {
.platform_data = &veu2h_platform_data,
},
.resource = veu2h_resources,
.num_resources = ARRAY_SIZE(veu2h_resources),
};
/* JPU */
static struct uio_info jpu_platform_data = {
.name = "JPU",
.version = "0",
.irq = intcs_evt2irq(0x560),
};
static struct resource jpu_resources[] = {
[0] = {
.name = "JPU",
.start = 0xfe980000,
.end = 0xfe9902d3,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device jpu_device = {
.name = "uio_pdrv_genirq",
.id = 6,
.dev = {
.platform_data = &jpu_platform_data,
},
.resource = jpu_resources,
.num_resources = ARRAY_SIZE(jpu_resources),
};
/* SPU1 */
static struct uio_info spu1_platform_data = {
.name = "SPU1",
.version = "0",
.irq = evt2irq(0xfc0),
};
static struct resource spu1_resources[] = {
[0] = {
.name = "SPU1",
.start = 0xfe300000,
.end = 0xfe3fffff,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device spu1_device = {
.name = "uio_pdrv_genirq",
.id = 7,
.dev = {
.platform_data = &spu1_platform_data,
},
.resource = spu1_resources,
.num_resources = ARRAY_SIZE(spu1_resources),
};
static struct platform_device *sh7367_early_devices[] __initdata = { static struct platform_device *sh7367_early_devices[] __initdata = {
&scif0_device, &scif0_device,
&scif1_device, &scif1_device,
...@@ -206,10 +415,24 @@ static struct platform_device *sh7367_early_devices[] __initdata = { ...@@ -206,10 +415,24 @@ static struct platform_device *sh7367_early_devices[] __initdata = {
&cmt10_device, &cmt10_device,
}; };
static struct platform_device *sh7367_devices[] __initdata = {
&vpu_device,
&veu0_device,
&veu1_device,
&veu2_device,
&veu3_device,
&veu2h_device,
&jpu_device,
&spu1_device,
};
void __init sh7367_add_standard_devices(void) void __init sh7367_add_standard_devices(void)
{ {
platform_add_devices(sh7367_early_devices, platform_add_devices(sh7367_early_devices,
ARRAY_SIZE(sh7367_early_devices)); ARRAY_SIZE(sh7367_early_devices));
platform_add_devices(sh7367_devices,
ARRAY_SIZE(sh7367_devices));
} }
#define SYMSTPCR2 0xe6158048 #define SYMSTPCR2 0xe6158048
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/uio_driver.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/io.h> #include <linux/io.h>
...@@ -601,6 +602,214 @@ static struct platform_device dma2_device = { ...@@ -601,6 +602,214 @@ static struct platform_device dma2_device = {
}, },
}; };
/* VPU */
static struct uio_info vpu_platform_data = {
.name = "VPU5HG",
.version = "0",
.irq = intcs_evt2irq(0x980),
};
static struct resource vpu_resources[] = {
[0] = {
.name = "VPU",
.start = 0xfe900000,
.end = 0xfe900157,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device vpu_device = {
.name = "uio_pdrv_genirq",
.id = 0,
.dev = {
.platform_data = &vpu_platform_data,
},
.resource = vpu_resources,
.num_resources = ARRAY_SIZE(vpu_resources),
};
/* VEU0 */
static struct uio_info veu0_platform_data = {
.name = "VEU0",
.version = "0",
.irq = intcs_evt2irq(0x700),
};
static struct resource veu0_resources[] = {
[0] = {
.name = "VEU0",
.start = 0xfe920000,
.end = 0xfe9200cb,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device veu0_device = {
.name = "uio_pdrv_genirq",
.id = 1,
.dev = {
.platform_data = &veu0_platform_data,
},
.resource = veu0_resources,
.num_resources = ARRAY_SIZE(veu0_resources),
};
/* VEU1 */
static struct uio_info veu1_platform_data = {
.name = "VEU1",
.version = "0",
.irq = intcs_evt2irq(0x720),
};
static struct resource veu1_resources[] = {
[0] = {
.name = "VEU1",
.start = 0xfe924000,
.end = 0xfe9240cb,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device veu1_device = {
.name = "uio_pdrv_genirq",
.id = 2,
.dev = {
.platform_data = &veu1_platform_data,
},
.resource = veu1_resources,
.num_resources = ARRAY_SIZE(veu1_resources),
};
/* VEU2 */
static struct uio_info veu2_platform_data = {
.name = "VEU2",
.version = "0",
.irq = intcs_evt2irq(0x740),
};
static struct resource veu2_resources[] = {
[0] = {
.name = "VEU2",
.start = 0xfe928000,
.end = 0xfe928307,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device veu2_device = {
.name = "uio_pdrv_genirq",
.id = 3,
.dev = {
.platform_data = &veu2_platform_data,
},
.resource = veu2_resources,
.num_resources = ARRAY_SIZE(veu2_resources),
};
/* VEU3 */
static struct uio_info veu3_platform_data = {
.name = "VEU3",
.version = "0",
.irq = intcs_evt2irq(0x760),
};
static struct resource veu3_resources[] = {
[0] = {
.name = "VEU3",
.start = 0xfe92c000,
.end = 0xfe92c307,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device veu3_device = {
.name = "uio_pdrv_genirq",
.id = 4,
.dev = {
.platform_data = &veu3_platform_data,
},
.resource = veu3_resources,
.num_resources = ARRAY_SIZE(veu3_resources),
};
/* JPU */
static struct uio_info jpu_platform_data = {
.name = "JPU",
.version = "0",
.irq = intcs_evt2irq(0x560),
};
static struct resource jpu_resources[] = {
[0] = {
.name = "JPU",
.start = 0xfe980000,
.end = 0xfe9902d3,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device jpu_device = {
.name = "uio_pdrv_genirq",
.id = 5,
.dev = {
.platform_data = &jpu_platform_data,
},
.resource = jpu_resources,
.num_resources = ARRAY_SIZE(jpu_resources),
};
/* SPU2DSP0 */
static struct uio_info spu0_platform_data = {
.name = "SPU2DSP0",
.version = "0",
.irq = evt2irq(0x1800),
};
static struct resource spu0_resources[] = {
[0] = {
.name = "SPU2DSP0",
.start = 0xfe200000,
.end = 0xfe2fffff,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device spu0_device = {
.name = "uio_pdrv_genirq",
.id = 6,
.dev = {
.platform_data = &spu0_platform_data,
},
.resource = spu0_resources,
.num_resources = ARRAY_SIZE(spu0_resources),
};
/* SPU2DSP1 */
static struct uio_info spu1_platform_data = {
.name = "SPU2DSP1",
.version = "0",
.irq = evt2irq(0x1820),
};
static struct resource spu1_resources[] = {
[0] = {
.name = "SPU2DSP1",
.start = 0xfe300000,
.end = 0xfe3fffff,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device spu1_device = {
.name = "uio_pdrv_genirq",
.id = 7,
.dev = {
.platform_data = &spu1_platform_data,
},
.resource = spu1_resources,
.num_resources = ARRAY_SIZE(spu1_resources),
};
static struct platform_device *sh7372_early_devices[] __initdata = { static struct platform_device *sh7372_early_devices[] __initdata = {
&scif0_device, &scif0_device,
&scif1_device, &scif1_device,
...@@ -620,6 +829,14 @@ static struct platform_device *sh7372_late_devices[] __initdata = { ...@@ -620,6 +829,14 @@ static struct platform_device *sh7372_late_devices[] __initdata = {
&dma0_device, &dma0_device,
&dma1_device, &dma1_device,
&dma2_device, &dma2_device,
&vpu_device,
&veu0_device,
&veu1_device,
&veu2_device,
&veu3_device,
&jpu_device,
&spu0_device,
&spu1_device,
}; };
void __init sh7372_add_standard_devices(void) void __init sh7372_add_standard_devices(void)
......
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/uio_driver.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/input.h> #include <linux/input.h>
#include <linux/io.h> #include <linux/io.h>
...@@ -38,7 +39,7 @@ static struct plat_sci_port scif0_platform_data = { ...@@ -38,7 +39,7 @@ static struct plat_sci_port scif0_platform_data = {
.flags = UPF_BOOT_AUTOCONF, .flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE, .scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_4, .scbrr_algo_id = SCBRR_ALGO_4,
.type = PORT_SCIF, .type = PORT_SCIFA,
.irqs = { evt2irq(0xc00), evt2irq(0xc00), .irqs = { evt2irq(0xc00), evt2irq(0xc00),
evt2irq(0xc00), evt2irq(0xc00) }, evt2irq(0xc00), evt2irq(0xc00) },
}; };
...@@ -57,7 +58,7 @@ static struct plat_sci_port scif1_platform_data = { ...@@ -57,7 +58,7 @@ static struct plat_sci_port scif1_platform_data = {
.flags = UPF_BOOT_AUTOCONF, .flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE, .scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_4, .scbrr_algo_id = SCBRR_ALGO_4,
.type = PORT_SCIF, .type = PORT_SCIFA,
.irqs = { evt2irq(0xc20), evt2irq(0xc20), .irqs = { evt2irq(0xc20), evt2irq(0xc20),
evt2irq(0xc20), evt2irq(0xc20) }, evt2irq(0xc20), evt2irq(0xc20) },
}; };
...@@ -76,7 +77,7 @@ static struct plat_sci_port scif2_platform_data = { ...@@ -76,7 +77,7 @@ static struct plat_sci_port scif2_platform_data = {
.flags = UPF_BOOT_AUTOCONF, .flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE, .scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_4, .scbrr_algo_id = SCBRR_ALGO_4,
.type = PORT_SCIF, .type = PORT_SCIFA,
.irqs = { evt2irq(0xc40), evt2irq(0xc40), .irqs = { evt2irq(0xc40), evt2irq(0xc40),
evt2irq(0xc40), evt2irq(0xc40) }, evt2irq(0xc40), evt2irq(0xc40) },
}; };
...@@ -95,7 +96,7 @@ static struct plat_sci_port scif3_platform_data = { ...@@ -95,7 +96,7 @@ static struct plat_sci_port scif3_platform_data = {
.flags = UPF_BOOT_AUTOCONF, .flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE, .scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_4, .scbrr_algo_id = SCBRR_ALGO_4,
.type = PORT_SCIF, .type = PORT_SCIFA,
.irqs = { evt2irq(0xc60), evt2irq(0xc60), .irqs = { evt2irq(0xc60), evt2irq(0xc60),
evt2irq(0xc60), evt2irq(0xc60) }, evt2irq(0xc60), evt2irq(0xc60) },
}; };
...@@ -114,7 +115,7 @@ static struct plat_sci_port scif4_platform_data = { ...@@ -114,7 +115,7 @@ static struct plat_sci_port scif4_platform_data = {
.flags = UPF_BOOT_AUTOCONF, .flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE, .scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_4, .scbrr_algo_id = SCBRR_ALGO_4,
.type = PORT_SCIF, .type = PORT_SCIFA,
.irqs = { evt2irq(0xd20), evt2irq(0xd20), .irqs = { evt2irq(0xd20), evt2irq(0xd20),
evt2irq(0xd20), evt2irq(0xd20) }, evt2irq(0xd20), evt2irq(0xd20) },
}; };
...@@ -133,7 +134,7 @@ static struct plat_sci_port scif5_platform_data = { ...@@ -133,7 +134,7 @@ static struct plat_sci_port scif5_platform_data = {
.flags = UPF_BOOT_AUTOCONF, .flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE, .scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_4, .scbrr_algo_id = SCBRR_ALGO_4,
.type = PORT_SCIF, .type = PORT_SCIFA,
.irqs = { evt2irq(0xd40), evt2irq(0xd40), .irqs = { evt2irq(0xd40), evt2irq(0xd40),
evt2irq(0xd40), evt2irq(0xd40) }, evt2irq(0xd40), evt2irq(0xd40) },
}; };
...@@ -152,7 +153,7 @@ static struct plat_sci_port scif6_platform_data = { ...@@ -152,7 +153,7 @@ static struct plat_sci_port scif6_platform_data = {
.flags = UPF_BOOT_AUTOCONF, .flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE, .scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_4, .scbrr_algo_id = SCBRR_ALGO_4,
.type = PORT_SCIF, .type = PORT_SCIFA,
.irqs = { intcs_evt2irq(0x1a80), intcs_evt2irq(0x1a80), .irqs = { intcs_evt2irq(0x1a80), intcs_evt2irq(0x1a80),
intcs_evt2irq(0x1a80), intcs_evt2irq(0x1a80) }, intcs_evt2irq(0x1a80), intcs_evt2irq(0x1a80) },
}; };
...@@ -171,7 +172,7 @@ static struct plat_sci_port scif7_platform_data = { ...@@ -171,7 +172,7 @@ static struct plat_sci_port scif7_platform_data = {
.flags = UPF_BOOT_AUTOCONF, .flags = UPF_BOOT_AUTOCONF,
.scscr = SCSCR_RE | SCSCR_TE, .scscr = SCSCR_RE | SCSCR_TE,
.scbrr_algo_id = SCBRR_ALGO_4, .scbrr_algo_id = SCBRR_ALGO_4,
.type = PORT_SCIF, .type = PORT_SCIFB,
.irqs = { evt2irq(0xd60), evt2irq(0xd60), .irqs = { evt2irq(0xd60), evt2irq(0xd60),
evt2irq(0xd60), evt2irq(0xd60) }, evt2irq(0xd60), evt2irq(0xd60) },
}; };
...@@ -215,6 +216,214 @@ static struct platform_device cmt10_device = { ...@@ -215,6 +216,214 @@ static struct platform_device cmt10_device = {
.num_resources = ARRAY_SIZE(cmt10_resources), .num_resources = ARRAY_SIZE(cmt10_resources),
}; };
/* VPU */
static struct uio_info vpu_platform_data = {
.name = "VPU5HG",
.version = "0",
.irq = intcs_evt2irq(0x980),
};
static struct resource vpu_resources[] = {
[0] = {
.name = "VPU",
.start = 0xfe900000,
.end = 0xfe900157,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device vpu_device = {
.name = "uio_pdrv_genirq",
.id = 0,
.dev = {
.platform_data = &vpu_platform_data,
},
.resource = vpu_resources,
.num_resources = ARRAY_SIZE(vpu_resources),
};
/* VEU0 */
static struct uio_info veu0_platform_data = {
.name = "VEU0",
.version = "0",
.irq = intcs_evt2irq(0x700),
};
static struct resource veu0_resources[] = {
[0] = {
.name = "VEU0",
.start = 0xfe920000,
.end = 0xfe9200cb,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device veu0_device = {
.name = "uio_pdrv_genirq",
.id = 1,
.dev = {
.platform_data = &veu0_platform_data,
},
.resource = veu0_resources,
.num_resources = ARRAY_SIZE(veu0_resources),
};
/* VEU1 */
static struct uio_info veu1_platform_data = {
.name = "VEU1",
.version = "0",
.irq = intcs_evt2irq(0x720),
};
static struct resource veu1_resources[] = {
[0] = {
.name = "VEU1",
.start = 0xfe924000,
.end = 0xfe9240cb,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device veu1_device = {
.name = "uio_pdrv_genirq",
.id = 2,
.dev = {
.platform_data = &veu1_platform_data,
},
.resource = veu1_resources,
.num_resources = ARRAY_SIZE(veu1_resources),
};
/* VEU2 */
static struct uio_info veu2_platform_data = {
.name = "VEU2",
.version = "0",
.irq = intcs_evt2irq(0x740),
};
static struct resource veu2_resources[] = {
[0] = {
.name = "VEU2",
.start = 0xfe928000,
.end = 0xfe928307,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device veu2_device = {
.name = "uio_pdrv_genirq",
.id = 3,
.dev = {
.platform_data = &veu2_platform_data,
},
.resource = veu2_resources,
.num_resources = ARRAY_SIZE(veu2_resources),
};
/* VEU3 */
static struct uio_info veu3_platform_data = {
.name = "VEU3",
.version = "0",
.irq = intcs_evt2irq(0x760),
};
static struct resource veu3_resources[] = {
[0] = {
.name = "VEU3",
.start = 0xfe92c000,
.end = 0xfe92c307,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device veu3_device = {
.name = "uio_pdrv_genirq",
.id = 4,
.dev = {
.platform_data = &veu3_platform_data,
},
.resource = veu3_resources,
.num_resources = ARRAY_SIZE(veu3_resources),
};
/* JPU */
static struct uio_info jpu_platform_data = {
.name = "JPU",
.version = "0",
.irq = intcs_evt2irq(0x560),
};
static struct resource jpu_resources[] = {
[0] = {
.name = "JPU",
.start = 0xfe980000,
.end = 0xfe9902d3,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device jpu_device = {
.name = "uio_pdrv_genirq",
.id = 5,
.dev = {
.platform_data = &jpu_platform_data,
},
.resource = jpu_resources,
.num_resources = ARRAY_SIZE(jpu_resources),
};
/* SPU2DSP0 */
static struct uio_info spu0_platform_data = {
.name = "SPU2DSP0",
.version = "0",
.irq = evt2irq(0x1800),
};
static struct resource spu0_resources[] = {
[0] = {
.name = "SPU2DSP0",
.start = 0xfe200000,
.end = 0xfe2fffff,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device spu0_device = {
.name = "uio_pdrv_genirq",
.id = 6,
.dev = {
.platform_data = &spu0_platform_data,
},
.resource = spu0_resources,
.num_resources = ARRAY_SIZE(spu0_resources),
};
/* SPU2DSP1 */
static struct uio_info spu1_platform_data = {
.name = "SPU2DSP1",
.version = "0",
.irq = evt2irq(0x1820),
};
static struct resource spu1_resources[] = {
[0] = {
.name = "SPU2DSP1",
.start = 0xfe300000,
.end = 0xfe3fffff,
.flags = IORESOURCE_MEM,
},
};
static struct platform_device spu1_device = {
.name = "uio_pdrv_genirq",
.id = 7,
.dev = {
.platform_data = &spu1_platform_data,
},
.resource = spu1_resources,
.num_resources = ARRAY_SIZE(spu1_resources),
};
static struct platform_device *sh7377_early_devices[] __initdata = { static struct platform_device *sh7377_early_devices[] __initdata = {
&scif0_device, &scif0_device,
&scif1_device, &scif1_device,
...@@ -227,10 +436,24 @@ static struct platform_device *sh7377_early_devices[] __initdata = { ...@@ -227,10 +436,24 @@ static struct platform_device *sh7377_early_devices[] __initdata = {
&cmt10_device, &cmt10_device,
}; };
static struct platform_device *sh7377_devices[] __initdata = {
&vpu_device,
&veu0_device,
&veu1_device,
&veu2_device,
&veu3_device,
&jpu_device,
&spu0_device,
&spu1_device,
};
void __init sh7377_add_standard_devices(void) void __init sh7377_add_standard_devices(void)
{ {
platform_add_devices(sh7377_early_devices, platform_add_devices(sh7377_early_devices,
ARRAY_SIZE(sh7377_early_devices)); ARRAY_SIZE(sh7377_early_devices));
platform_add_devices(sh7377_devices,
ARRAY_SIZE(sh7377_devices));
} }
#define SMSTPCR3 0xe615013c #define SMSTPCR3 0xe615013c
......
...@@ -27,9 +27,11 @@ ...@@ -27,9 +27,11 @@
#include <linux/input.h> #include <linux/input.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/serial_sci.h> #include <linux/serial_sci.h>
#include <linux/sh_dma.h>
#include <linux/sh_intc.h> #include <linux/sh_intc.h>
#include <linux/sh_timer.h> #include <linux/sh_timer.h>
#include <mach/hardware.h> #include <mach/hardware.h>
#include <mach/sh73a0.h>
#include <asm/mach-types.h> #include <asm/mach-types.h>
#include <asm/mach/arch.h> #include <asm/mach/arch.h>
...@@ -392,6 +394,242 @@ static struct platform_device i2c4_device = { ...@@ -392,6 +394,242 @@ static struct platform_device i2c4_device = {
.num_resources = ARRAY_SIZE(i2c4_resources), .num_resources = ARRAY_SIZE(i2c4_resources),
}; };
/* Transmit sizes and respective CHCR register values */
enum {
XMIT_SZ_8BIT = 0,
XMIT_SZ_16BIT = 1,
XMIT_SZ_32BIT = 2,
XMIT_SZ_64BIT = 7,
XMIT_SZ_128BIT = 3,
XMIT_SZ_256BIT = 4,
XMIT_SZ_512BIT = 5,
};
/* log2(size / 8) - used to calculate number of transfers */
#define TS_SHIFT { \
[XMIT_SZ_8BIT] = 0, \
[XMIT_SZ_16BIT] = 1, \
[XMIT_SZ_32BIT] = 2, \
[XMIT_SZ_64BIT] = 3, \
[XMIT_SZ_128BIT] = 4, \
[XMIT_SZ_256BIT] = 5, \
[XMIT_SZ_512BIT] = 6, \
}
#define TS_INDEX2VAL(i) ((((i) & 3) << 3) | (((i) & 0xc) << (20 - 2)))
#define CHCR_TX(xmit_sz) (DM_FIX | SM_INC | 0x800 | TS_INDEX2VAL((xmit_sz)))
#define CHCR_RX(xmit_sz) (DM_INC | SM_FIX | 0x800 | TS_INDEX2VAL((xmit_sz)))
static const struct sh_dmae_slave_config sh73a0_dmae_slaves[] = {
{
.slave_id = SHDMA_SLAVE_SCIF0_TX,
.addr = 0xe6c40020,
.chcr = CHCR_TX(XMIT_SZ_8BIT),
.mid_rid = 0x21,
}, {
.slave_id = SHDMA_SLAVE_SCIF0_RX,
.addr = 0xe6c40024,
.chcr = CHCR_RX(XMIT_SZ_8BIT),
.mid_rid = 0x22,
}, {
.slave_id = SHDMA_SLAVE_SCIF1_TX,
.addr = 0xe6c50020,
.chcr = CHCR_TX(XMIT_SZ_8BIT),
.mid_rid = 0x25,
}, {
.slave_id = SHDMA_SLAVE_SCIF1_RX,
.addr = 0xe6c50024,
.chcr = CHCR_RX(XMIT_SZ_8BIT),
.mid_rid = 0x26,
}, {
.slave_id = SHDMA_SLAVE_SCIF2_TX,
.addr = 0xe6c60020,
.chcr = CHCR_TX(XMIT_SZ_8BIT),
.mid_rid = 0x29,
}, {
.slave_id = SHDMA_SLAVE_SCIF2_RX,
.addr = 0xe6c60024,
.chcr = CHCR_RX(XMIT_SZ_8BIT),
.mid_rid = 0x2a,
}, {
.slave_id = SHDMA_SLAVE_SCIF3_TX,
.addr = 0xe6c70020,
.chcr = CHCR_TX(XMIT_SZ_8BIT),
.mid_rid = 0x2d,
}, {
.slave_id = SHDMA_SLAVE_SCIF3_RX,
.addr = 0xe6c70024,
.chcr = CHCR_RX(XMIT_SZ_8BIT),
.mid_rid = 0x2e,
}, {
.slave_id = SHDMA_SLAVE_SCIF4_TX,
.addr = 0xe6c80020,
.chcr = CHCR_TX(XMIT_SZ_8BIT),
.mid_rid = 0x39,
}, {
.slave_id = SHDMA_SLAVE_SCIF4_RX,
.addr = 0xe6c80024,
.chcr = CHCR_RX(XMIT_SZ_8BIT),
.mid_rid = 0x3a,
}, {
.slave_id = SHDMA_SLAVE_SCIF5_TX,
.addr = 0xe6cb0020,
.chcr = CHCR_TX(XMIT_SZ_8BIT),
.mid_rid = 0x35,
}, {
.slave_id = SHDMA_SLAVE_SCIF5_RX,
.addr = 0xe6cb0024,
.chcr = CHCR_RX(XMIT_SZ_8BIT),
.mid_rid = 0x36,
}, {
.slave_id = SHDMA_SLAVE_SCIF6_TX,
.addr = 0xe6cc0020,
.chcr = CHCR_TX(XMIT_SZ_8BIT),
.mid_rid = 0x1d,
}, {
.slave_id = SHDMA_SLAVE_SCIF6_RX,
.addr = 0xe6cc0024,
.chcr = CHCR_RX(XMIT_SZ_8BIT),
.mid_rid = 0x1e,
}, {
.slave_id = SHDMA_SLAVE_SCIF7_TX,
.addr = 0xe6cd0020,
.chcr = CHCR_TX(XMIT_SZ_8BIT),
.mid_rid = 0x19,
}, {
.slave_id = SHDMA_SLAVE_SCIF7_RX,
.addr = 0xe6cd0024,
.chcr = CHCR_RX(XMIT_SZ_8BIT),
.mid_rid = 0x1a,
}, {
.slave_id = SHDMA_SLAVE_SCIF8_TX,
.addr = 0xe6c30040,
.chcr = CHCR_TX(XMIT_SZ_8BIT),
.mid_rid = 0x3d,
}, {
.slave_id = SHDMA_SLAVE_SCIF8_RX,
.addr = 0xe6c30060,
.chcr = CHCR_RX(XMIT_SZ_8BIT),
.mid_rid = 0x3e,
}, {
.slave_id = SHDMA_SLAVE_SDHI0_TX,
.addr = 0xee100030,
.chcr = CHCR_TX(XMIT_SZ_16BIT),
.mid_rid = 0xc1,
}, {
.slave_id = SHDMA_SLAVE_SDHI0_RX,
.addr = 0xee100030,
.chcr = CHCR_RX(XMIT_SZ_16BIT),
.mid_rid = 0xc2,
}, {
.slave_id = SHDMA_SLAVE_SDHI1_TX,
.addr = 0xee120030,
.chcr = CHCR_TX(XMIT_SZ_16BIT),
.mid_rid = 0xc9,
}, {
.slave_id = SHDMA_SLAVE_SDHI1_RX,
.addr = 0xee120030,
.chcr = CHCR_RX(XMIT_SZ_16BIT),
.mid_rid = 0xca,
}, {
.slave_id = SHDMA_SLAVE_SDHI2_TX,
.addr = 0xee140030,
.chcr = CHCR_TX(XMIT_SZ_16BIT),
.mid_rid = 0xcd,
}, {
.slave_id = SHDMA_SLAVE_SDHI2_RX,
.addr = 0xee140030,
.chcr = CHCR_RX(XMIT_SZ_16BIT),
.mid_rid = 0xce,
}, {
.slave_id = SHDMA_SLAVE_MMCIF_TX,
.addr = 0xe6bd0034,
.chcr = CHCR_TX(XMIT_SZ_32BIT),
.mid_rid = 0xd1,
}, {
.slave_id = SHDMA_SLAVE_MMCIF_RX,
.addr = 0xe6bd0034,
.chcr = CHCR_RX(XMIT_SZ_32BIT),
.mid_rid = 0xd2,
},
};
#define DMAE_CHANNEL(_offset) \
{ \
.offset = _offset - 0x20, \
.dmars = _offset - 0x20 + 0x40, \
}
static const struct sh_dmae_channel sh73a0_dmae_channels[] = {
DMAE_CHANNEL(0x8000),
DMAE_CHANNEL(0x8080),
DMAE_CHANNEL(0x8100),
DMAE_CHANNEL(0x8180),
DMAE_CHANNEL(0x8200),
DMAE_CHANNEL(0x8280),
DMAE_CHANNEL(0x8300),
DMAE_CHANNEL(0x8380),
DMAE_CHANNEL(0x8400),
DMAE_CHANNEL(0x8480),
DMAE_CHANNEL(0x8500),
DMAE_CHANNEL(0x8580),
DMAE_CHANNEL(0x8600),
DMAE_CHANNEL(0x8680),
DMAE_CHANNEL(0x8700),
DMAE_CHANNEL(0x8780),
DMAE_CHANNEL(0x8800),
DMAE_CHANNEL(0x8880),
DMAE_CHANNEL(0x8900),
DMAE_CHANNEL(0x8980),
};
static const unsigned int ts_shift[] = TS_SHIFT;
static struct sh_dmae_pdata sh73a0_dmae_platform_data = {
.slave = sh73a0_dmae_slaves,
.slave_num = ARRAY_SIZE(sh73a0_dmae_slaves),
.channel = sh73a0_dmae_channels,
.channel_num = ARRAY_SIZE(sh73a0_dmae_channels),
.ts_low_shift = 3,
.ts_low_mask = 0x18,
.ts_high_shift = (20 - 2), /* 2 bits for shifted low TS */
.ts_high_mask = 0x00300000,
.ts_shift = ts_shift,
.ts_shift_num = ARRAY_SIZE(ts_shift),
.dmaor_init = DMAOR_DME,
};
static struct resource sh73a0_dmae_resources[] = {
{
/* Registers including DMAOR and channels including DMARSx */
.start = 0xfe000020,
.end = 0xfe008a00 - 1,
.flags = IORESOURCE_MEM,
},
{
/* DMA error IRQ */
.start = gic_spi(129),
.end = gic_spi(129),
.flags = IORESOURCE_IRQ,
},
{
/* IRQ for channels 0-19 */
.start = gic_spi(109),
.end = gic_spi(128),
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device dma0_device = {
.name = "sh-dma-engine",
.id = 0,
.resource = sh73a0_dmae_resources,
.num_resources = ARRAY_SIZE(sh73a0_dmae_resources),
.dev = {
.platform_data = &sh73a0_dmae_platform_data,
},
};
static struct platform_device *sh73a0_early_devices[] __initdata = { static struct platform_device *sh73a0_early_devices[] __initdata = {
&scif0_device, &scif0_device,
&scif1_device, &scif1_device,
...@@ -413,10 +651,16 @@ static struct platform_device *sh73a0_late_devices[] __initdata = { ...@@ -413,10 +651,16 @@ static struct platform_device *sh73a0_late_devices[] __initdata = {
&i2c2_device, &i2c2_device,
&i2c3_device, &i2c3_device,
&i2c4_device, &i2c4_device,
&dma0_device,
}; };
#define SRCR2 0xe61580b0
void __init sh73a0_add_standard_devices(void) void __init sh73a0_add_standard_devices(void)
{ {
/* Clear software reset bit on SY-DMAC module */
__raw_writel(__raw_readl(SRCR2) & ~(1 << 18), SRCR2);
platform_add_devices(sh73a0_early_devices, platform_add_devices(sh73a0_early_devices,
ARRAY_SIZE(sh73a0_early_devices)); ARRAY_SIZE(sh73a0_early_devices));
platform_add_devices(sh73a0_late_devices, platform_add_devices(sh73a0_late_devices,
......
/*
* sh7372 lowlevel sleep code for "Core Standby Mode"
*
* Copyright (C) 2011 Magnus Damm
*
* In "Core Standby Mode" the ARM core is off, but L2 cache is still on
*
* Based on mach-omap2/sleep34xx.S
*
* (C) Copyright 2007 Texas Instruments
* Karthik Dasu <karthik-dp@ti.com>
*
* (C) Copyright 2004 Texas Instruments, <www.ti.com>
* Richard Woodruff <r-woodruff2@ti.com>
*
* 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., 59 Temple Place, Suite 330, Boston,
* MA 02111-1307 USA
*/
#include <linux/linkage.h>
#include <asm/assembler.h>
#define SMFRAM 0xe6a70000
.align
kernel_flush:
.word v7_flush_dcache_all
.align 3
ENTRY(sh7372_cpu_suspend)
stmfd sp!, {r0-r12, lr} @ save registers on stack
ldr r8, =SMFRAM
mov r4, sp @ Store sp
mrs r5, spsr @ Store spsr
mov r6, lr @ Store lr
stmia r8!, {r4-r6}
mrc p15, 0, r4, c1, c0, 2 @ Coprocessor access control register
mrc p15, 0, r5, c2, c0, 0 @ TTBR0
mrc p15, 0, r6, c2, c0, 1 @ TTBR1
mrc p15, 0, r7, c2, c0, 2 @ TTBCR
stmia r8!, {r4-r7}
mrc p15, 0, r4, c3, c0, 0 @ Domain access Control Register
mrc p15, 0, r5, c10, c2, 0 @ PRRR
mrc p15, 0, r6, c10, c2, 1 @ NMRR
stmia r8!,{r4-r6}
mrc p15, 0, r4, c13, c0, 1 @ Context ID
mrc p15, 0, r5, c13, c0, 2 @ User r/w thread and process ID
mrc p15, 0, r6, c12, c0, 0 @ Secure or NS vector base address
mrs r7, cpsr @ Store current cpsr
stmia r8!, {r4-r7}
mrc p15, 0, r4, c1, c0, 0 @ save control register
stmia r8!, {r4}
/*
* jump out to kernel flush routine
* - reuse that code is better
* - it executes in a cached space so is faster than refetch per-block
* - should be faster and will change with kernel
* - 'might' have to copy address, load and jump to it
* Flush all data from the L1 data cache before disabling
* SCTLR.C bit.
*/
ldr r1, kernel_flush
mov lr, pc
bx r1
/*
* Clear the SCTLR.C bit to prevent further data cache
* allocation. Clearing SCTLR.C would make all the data accesses
* strongly ordered and would not hit the cache.
*/
mrc p15, 0, r0, c1, c0, 0
bic r0, r0, #(1 << 2) @ Disable the C bit
mcr p15, 0, r0, c1, c0, 0
isb
/*
* Invalidate L1 data cache. Even though only invalidate is
* necessary exported flush API is used here. Doing clean
* on already clean cache would be almost NOP.
*/
ldr r1, kernel_flush
blx r1
/*
* The kernel doesn't interwork: v7_flush_dcache_all in particluar will
* always return in Thumb state when CONFIG_THUMB2_KERNEL is enabled.
* This sequence switches back to ARM. Note that .align may insert a
* nop: bx pc needs to be word-aligned in order to work.
*/
THUMB( .thumb )
THUMB( .align )
THUMB( bx pc )
THUMB( nop )
.arm
/* Data memory barrier and Data sync barrier */
dsb
dmb
/*
* ===================================
* == WFI instruction => Enter idle ==
* ===================================
*/
wfi @ wait for interrupt
/*
* ===================================
* == Resume path for non-OFF modes ==
* ===================================
*/
mrc p15, 0, r0, c1, c0, 0
tst r0, #(1 << 2) @ Check C bit enabled?
orreq r0, r0, #(1 << 2) @ Enable the C bit if cleared
mcreq p15, 0, r0, c1, c0, 0
isb
/*
* ===================================
* == Exit point from non-OFF modes ==
* ===================================
*/
ldmfd sp!, {r0-r12, pc} @ restore regs and return
.pool
.align 12
.text
.global sh7372_cpu_resume
sh7372_cpu_resume:
mov r1, #0
/*
* Invalidate all instruction caches to PoU
* and flush branch target cache
*/
mcr p15, 0, r1, c7, c5, 0
ldr r3, =SMFRAM
ldmia r3!, {r4-r6}
mov sp, r4 @ Restore sp
msr spsr_cxsf, r5 @ Restore spsr
mov lr, r6 @ Restore lr
ldmia r3!, {r4-r7}
mcr p15, 0, r4, c1, c0, 2 @ Coprocessor access Control Register
mcr p15, 0, r5, c2, c0, 0 @ TTBR0
mcr p15, 0, r6, c2, c0, 1 @ TTBR1
mcr p15, 0, r7, c2, c0, 2 @ TTBCR
ldmia r3!,{r4-r6}
mcr p15, 0, r4, c3, c0, 0 @ Domain access Control Register
mcr p15, 0, r5, c10, c2, 0 @ PRRR
mcr p15, 0, r6, c10, c2, 1 @ NMRR
ldmia r3!,{r4-r7}
mcr p15, 0, r4, c13, c0, 1 @ Context ID
mcr p15, 0, r5, c13, c0, 2 @ User r/w thread and process ID
mrc p15, 0, r6, c12, c0, 0 @ Secure or NS vector base address
msr cpsr, r7 @ store cpsr
/* Starting to enable MMU here */
mrc p15, 0, r7, c2, c0, 2 @ Read TTBRControl
/* Extract N (0:2) bits and decide whether to use TTBR0 or TTBR1 */
and r7, #0x7
cmp r7, #0x0
beq usettbr0
ttbr_error:
/*
* More work needs to be done to support N[0:2] value other than 0
* So looping here so that the error can be detected
*/
b ttbr_error
.align
cache_pred_disable_mask:
.word 0xFFFFE7FB
ttbrbit_mask:
.word 0xFFFFC000
table_index_mask:
.word 0xFFF00000
table_entry:
.word 0x00000C02
usettbr0:
mrc p15, 0, r2, c2, c0, 0
ldr r5, ttbrbit_mask
and r2, r5
mov r4, pc
ldr r5, table_index_mask
and r4, r5 @ r4 = 31 to 20 bits of pc
/* Extract the value to be written to table entry */
ldr r6, table_entry
/* r6 has the value to be written to table entry */
add r6, r6, r4
/* Getting the address of table entry to modify */
lsr r4, #18
/* r2 has the location which needs to be modified */
add r2, r4
ldr r4, [r2]
str r6, [r2] /* modify the table entry */
mov r7, r6
mov r5, r2
mov r6, r4
/* r5 = original page table address */
/* r6 = original page table data */
mov r0, #0
mcr p15, 0, r0, c7, c5, 4 @ Flush prefetch buffer
mcr p15, 0, r0, c7, c5, 6 @ Invalidate branch predictor array
mcr p15, 0, r0, c8, c5, 0 @ Invalidate instruction TLB
mcr p15, 0, r0, c8, c6, 0 @ Invalidate data TLB
/*
* Restore control register. This enables the MMU.
* The caches and prediction are not enabled here, they
* will be enabled after restoring the MMU table entry.
*/
ldmia r3!, {r4}
stmia r3!, {r5} /* save original page table address */
stmia r3!, {r6} /* save original page table data */
stmia r3!, {r7} /* save modified page table data */
ldr r2, cache_pred_disable_mask
and r4, r2
mcr p15, 0, r4, c1, c0, 0
dsb
isb
ldr r0, =restoremmu_on
bx r0
/*
* ==============================
* == Exit point from OFF mode ==
* ==============================
*/
restoremmu_on:
ldmfd sp!, {r0-r12, pc} @ restore regs and return
...@@ -59,6 +59,11 @@ unsigned int __init sh73a0_get_core_count(void) ...@@ -59,6 +59,11 @@ unsigned int __init sh73a0_get_core_count(void)
{ {
void __iomem *scu_base = scu_base_addr(); void __iomem *scu_base = scu_base_addr();
#ifdef CONFIG_HAVE_ARM_TWD
/* twd_base needs to be initialized before percpu_timer_setup() */
twd_base = (void __iomem *)0xf0000600;
#endif
return scu_get_core_count(scu_base); return scu_get_core_count(scu_base);
} }
...@@ -82,10 +87,6 @@ int __cpuinit sh73a0_boot_secondary(unsigned int cpu) ...@@ -82,10 +87,6 @@ int __cpuinit sh73a0_boot_secondary(unsigned int cpu)
void __init sh73a0_smp_prepare_cpus(void) void __init sh73a0_smp_prepare_cpus(void)
{ {
#ifdef CONFIG_HAVE_ARM_TWD
twd_base = (void __iomem *)0xf0000600;
#endif
scu_enable(scu_base_addr()); scu_enable(scu_base_addr());
/* Map the reset vector (in headsmp.S) */ /* Map the reset vector (in headsmp.S) */
......
/*
* Suspend-to-RAM support code for SH-Mobile ARM
*
* Copyright (C) 2011 Magnus Damm
*
* 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.
*/
#include <linux/pm.h>
#include <linux/suspend.h>
#include <linux/module.h>
#include <linux/err.h>
#include <asm/system.h>
#include <asm/io.h>
static int shmobile_suspend_default_enter(suspend_state_t suspend_state)
{
cpu_do_idle();
return 0;
}
static int shmobile_suspend_begin(suspend_state_t state)
{
disable_hlt();
return 0;
}
static void shmobile_suspend_end(void)
{
enable_hlt();
}
struct platform_suspend_ops shmobile_suspend_ops = {
.begin = shmobile_suspend_begin,
.end = shmobile_suspend_end,
.enter = shmobile_suspend_default_enter,
.valid = suspend_valid_only_mem,
};
static int __init shmobile_suspend_init(void)
{
suspend_set_ops(&shmobile_suspend_ops);
return 0;
}
late_initcall(shmobile_suspend_init);
...@@ -213,12 +213,17 @@ static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val) ...@@ -213,12 +213,17 @@ static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val)
struct sh_dmae_device, common); struct sh_dmae_device, common);
struct sh_dmae_pdata *pdata = shdev->pdata; struct sh_dmae_pdata *pdata = shdev->pdata;
const struct sh_dmae_channel *chan_pdata = &pdata->channel[sh_chan->id]; const struct sh_dmae_channel *chan_pdata = &pdata->channel[sh_chan->id];
u16 __iomem *addr = shdev->dmars + chan_pdata->dmars / sizeof(u16); u16 __iomem *addr = shdev->dmars;
int shift = chan_pdata->dmars_bit; int shift = chan_pdata->dmars_bit;
if (dmae_is_busy(sh_chan)) if (dmae_is_busy(sh_chan))
return -EBUSY; return -EBUSY;
/* in the case of a missing DMARS resource use first memory window */
if (!addr)
addr = (u16 __iomem *)shdev->chan_reg;
addr += chan_pdata->dmars / sizeof(u16);
__raw_writew((__raw_readw(addr) & (0xff00 >> shift)) | (val << shift), __raw_writew((__raw_readw(addr) & (0xff00 >> shift)) | (val << shift),
addr); addr);
...@@ -1078,7 +1083,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev) ...@@ -1078,7 +1083,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
unsigned long irqflags = IRQF_DISABLED, unsigned long irqflags = IRQF_DISABLED,
chan_flag[SH_DMAC_MAX_CHANNELS] = {}; chan_flag[SH_DMAC_MAX_CHANNELS] = {};
int errirq, chan_irq[SH_DMAC_MAX_CHANNELS]; int errirq, chan_irq[SH_DMAC_MAX_CHANNELS];
int err, i, irq_cnt = 0, irqres = 0; int err, i, irq_cnt = 0, irqres = 0, irq_cap = 0;
struct sh_dmae_device *shdev; struct sh_dmae_device *shdev;
struct resource *chan, *dmars, *errirq_res, *chanirq_res; struct resource *chan, *dmars, *errirq_res, *chanirq_res;
...@@ -1087,7 +1092,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev) ...@@ -1087,7 +1092,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
return -ENODEV; return -ENODEV;
chan = platform_get_resource(pdev, IORESOURCE_MEM, 0); chan = platform_get_resource(pdev, IORESOURCE_MEM, 0);
/* DMARS area is optional, if absent, this controller cannot do slave DMA */ /* DMARS area is optional */
dmars = platform_get_resource(pdev, IORESOURCE_MEM, 1); dmars = platform_get_resource(pdev, IORESOURCE_MEM, 1);
/* /*
* IRQ resources: * IRQ resources:
...@@ -1154,7 +1159,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev) ...@@ -1154,7 +1159,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&shdev->common.channels); INIT_LIST_HEAD(&shdev->common.channels);
dma_cap_set(DMA_MEMCPY, shdev->common.cap_mask); dma_cap_set(DMA_MEMCPY, shdev->common.cap_mask);
if (dmars) if (pdata->slave && pdata->slave_num)
dma_cap_set(DMA_SLAVE, shdev->common.cap_mask); dma_cap_set(DMA_SLAVE, shdev->common.cap_mask);
shdev->common.device_alloc_chan_resources shdev->common.device_alloc_chan_resources
...@@ -1203,8 +1208,13 @@ static int __init sh_dmae_probe(struct platform_device *pdev) ...@@ -1203,8 +1208,13 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
!platform_get_resource(pdev, IORESOURCE_IRQ, 1)) { !platform_get_resource(pdev, IORESOURCE_IRQ, 1)) {
/* Special case - all multiplexed */ /* Special case - all multiplexed */
for (; irq_cnt < pdata->channel_num; irq_cnt++) { for (; irq_cnt < pdata->channel_num; irq_cnt++) {
if (irq_cnt < SH_DMAC_MAX_CHANNELS) {
chan_irq[irq_cnt] = chanirq_res->start; chan_irq[irq_cnt] = chanirq_res->start;
chan_flag[irq_cnt] = IRQF_SHARED; chan_flag[irq_cnt] = IRQF_SHARED;
} else {
irq_cap = 1;
break;
}
} }
} else { } else {
do { do {
...@@ -1218,22 +1228,32 @@ static int __init sh_dmae_probe(struct platform_device *pdev) ...@@ -1218,22 +1228,32 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
"Found IRQ %d for channel %d\n", "Found IRQ %d for channel %d\n",
i, irq_cnt); i, irq_cnt);
chan_irq[irq_cnt++] = i; chan_irq[irq_cnt++] = i;
if (irq_cnt >= SH_DMAC_MAX_CHANNELS)
break;
}
if (irq_cnt >= SH_DMAC_MAX_CHANNELS) {
irq_cap = 1;
break;
} }
chanirq_res = platform_get_resource(pdev, chanirq_res = platform_get_resource(pdev,
IORESOURCE_IRQ, ++irqres); IORESOURCE_IRQ, ++irqres);
} while (irq_cnt < pdata->channel_num && chanirq_res); } while (irq_cnt < pdata->channel_num && chanirq_res);
} }
if (irq_cnt < pdata->channel_num)
goto eirqres;
/* Create DMA Channel */ /* Create DMA Channel */
for (i = 0; i < pdata->channel_num; i++) { for (i = 0; i < irq_cnt; i++) {
err = sh_dmae_chan_probe(shdev, i, chan_irq[i], chan_flag[i]); err = sh_dmae_chan_probe(shdev, i, chan_irq[i], chan_flag[i]);
if (err) if (err)
goto chan_probe_err; goto chan_probe_err;
} }
if (irq_cap)
dev_notice(&pdev->dev, "Attempting to register %d DMA "
"channels when a maximum of %d are supported.\n",
pdata->channel_num, SH_DMAC_MAX_CHANNELS);
pm_runtime_put(&pdev->dev); pm_runtime_put(&pdev->dev);
platform_set_drvdata(pdev, shdev); platform_set_drvdata(pdev, shdev);
...@@ -1243,7 +1263,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev) ...@@ -1243,7 +1263,7 @@ static int __init sh_dmae_probe(struct platform_device *pdev)
chan_probe_err: chan_probe_err:
sh_dmae_chan_remove(shdev); sh_dmae_chan_remove(shdev);
eirqres:
#if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE) #if defined(CONFIG_CPU_SH4) || defined(CONFIG_ARCH_SHMOBILE)
free_irq(errirq, shdev); free_irq(errirq, shdev);
eirq_err: eirq_err:
......
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/list.h> #include <linux/list.h>
#define SH_DMAC_MAX_CHANNELS 6 #define SH_DMAC_MAX_CHANNELS 20
#define SH_DMA_SLAVE_NUMBER 256 #define SH_DMA_SLAVE_NUMBER 256
#define SH_DMA_TCR_MAX 0x00FFFFFF /* 16MB */ #define SH_DMA_TCR_MAX 0x00FFFFFF /* 16MB */
......
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