Commit 241eb956 authored by Linus Torvalds's avatar Linus Torvalds

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

* 'sh-latest' of git://git.kernel.org/pub/scm/linux/kernel/git/lethal/sh-2.6: (34 commits)
  sh: Convert to generic show_interrupts.
  sh: Wire up new fhandle and clock_adjtime syscalls.
  sh: modify platform_device for sh_eth driver
  sh: add GETHER's platform_device in board-sh7757lcr
  sh: update sh7757lcr_defconfig
  sh: add platform_device of tmio_mmc and sh_mmcif to sh7757lcr
  sh: dmaengine support for SH7757
  sh: add mmc clock in clock-sh7757
  sh: add spi_board_info in sh7757lcr
  sh: add platform_device for SPI
  sh: add USB_ARCH_HAS_EHCI and OHCI for SH7757
  sh: Rename cpuidle states to fit general conventions
  serial: sh-sci: fix deadlock when resuming from S3 sleep
  sh: Enable CONFIG_GCOV_PROFILE_ALL for sh
  sh: Fix up async PCIe probing on SMP.
  serial: sh-sci: Kill off the special earlyprintk device.
  serial: sh-sci: Use dev_name() for region reservations.
  serial: sh-sci: Fix up earlyprintk port mapping.
  serial: sh-sci: Limit early console to one device.
  serial: sh-sci: Fix up break timer scheduling race.
  ...
parents fd34b0de 3d44ae40
...@@ -25,6 +25,7 @@ config SUPERH ...@@ -25,6 +25,7 @@ config SUPERH
select GENERIC_ATOMIC64 select GENERIC_ATOMIC64
# Support the deprecated APIs until MFD and GPIOLIB catch up. # Support the deprecated APIs until MFD and GPIOLIB catch up.
select GENERIC_HARDIRQS_NO_DEPRECATED if !MFD_SUPPORT && !GPIOLIB select GENERIC_HARDIRQS_NO_DEPRECATED if !MFD_SUPPORT && !GPIOLIB
select GENERIC_IRQ_SHOW
help help
The SuperH is a RISC processor targeted for use in embedded systems The SuperH is a RISC processor targeted for use in embedded systems
and consumer electronics; it was also used in the Sega Dreamcast and consumer electronics; it was also used in the Sega Dreamcast
...@@ -434,6 +435,8 @@ config CPU_SUBTYPE_SH7757 ...@@ -434,6 +435,8 @@ config CPU_SUBTYPE_SH7757
select CPU_SH4A select CPU_SH4A
select CPU_SHX2 select CPU_SHX2
select ARCH_WANT_OPTIONAL_GPIOLIB select ARCH_WANT_OPTIONAL_GPIOLIB
select USB_ARCH_HAS_OHCI
select USB_ARCH_HAS_EHCI
help help
Select SH7757 if you have a SH4A SH7757 CPU. Select SH7757 if you have a SH4A SH7757 CPU.
......
...@@ -66,6 +66,11 @@ static struct resource sh_eth_resources[] = { ...@@ -66,6 +66,11 @@ static struct resource sh_eth_resources[] = {
.end = 0xFEE00F7C - 1, .end = 0xFEE00F7C - 1,
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
}, { }, {
.start = 0xFEE01800, /* TSU */
.end = 0xFEE01FFF,
.flags = IORESOURCE_MEM,
}, {
.start = 57, /* irq number */ .start = 57, /* irq number */
.flags = IORESOURCE_IRQ, .flags = IORESOURCE_IRQ,
}, },
...@@ -74,6 +79,8 @@ static struct resource sh_eth_resources[] = { ...@@ -74,6 +79,8 @@ static struct resource sh_eth_resources[] = {
static struct sh_eth_plat_data sh7763_eth_pdata = { static struct sh_eth_plat_data sh7763_eth_pdata = {
.phy = 0, .phy = 0,
.edmac_endian = EDMAC_LITTLE_ENDIAN, .edmac_endian = EDMAC_LITTLE_ENDIAN,
.register_type = SH_ETH_REG_GIGABIT,
.phy_interface = PHY_INTERFACE_MODE_MII,
}; };
static struct platform_device espt_eth_device = { static struct platform_device espt_eth_device = {
......
...@@ -15,6 +15,9 @@ ...@@ -15,6 +15,9 @@
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/spi/flash.h> #include <linux/spi/flash.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/mmc/host.h>
#include <linux/mmc/sh_mmcif.h>
#include <linux/mfd/sh_mobile_sdhi.h>
#include <cpu/sh7757.h> #include <cpu/sh7757.h>
#include <asm/sh_eth.h> #include <asm/sh_eth.h>
#include <asm/heartbeat.h> #include <asm/heartbeat.h>
...@@ -44,6 +47,17 @@ static struct platform_device heartbeat_device = { ...@@ -44,6 +47,17 @@ static struct platform_device heartbeat_device = {
}; };
/* Fast Ethernet */ /* Fast Ethernet */
#define GBECONT 0xffc10100
#define GBECONT_RMII1 BIT(17)
#define GBECONT_RMII0 BIT(16)
static void sh7757_eth_set_mdio_gate(unsigned long addr)
{
if ((addr & 0x00000fff) < 0x0800)
writel(readl(GBECONT) | GBECONT_RMII0, GBECONT);
else
writel(readl(GBECONT) | GBECONT_RMII1, GBECONT);
}
static struct resource sh_eth0_resources[] = { static struct resource sh_eth0_resources[] = {
{ {
.start = 0xfef00000, .start = 0xfef00000,
...@@ -59,6 +73,8 @@ static struct resource sh_eth0_resources[] = { ...@@ -59,6 +73,8 @@ static struct resource sh_eth0_resources[] = {
static struct sh_eth_plat_data sh7757_eth0_pdata = { static struct sh_eth_plat_data sh7757_eth0_pdata = {
.phy = 1, .phy = 1,
.edmac_endian = EDMAC_LITTLE_ENDIAN, .edmac_endian = EDMAC_LITTLE_ENDIAN,
.register_type = SH_ETH_REG_FAST_SH4,
.set_mdio_gate = sh7757_eth_set_mdio_gate,
}; };
static struct platform_device sh7757_eth0_device = { static struct platform_device sh7757_eth0_device = {
...@@ -86,6 +102,8 @@ static struct resource sh_eth1_resources[] = { ...@@ -86,6 +102,8 @@ static struct resource sh_eth1_resources[] = {
static struct sh_eth_plat_data sh7757_eth1_pdata = { static struct sh_eth_plat_data sh7757_eth1_pdata = {
.phy = 1, .phy = 1,
.edmac_endian = EDMAC_LITTLE_ENDIAN, .edmac_endian = EDMAC_LITTLE_ENDIAN,
.register_type = SH_ETH_REG_FAST_SH4,
.set_mdio_gate = sh7757_eth_set_mdio_gate,
}; };
static struct platform_device sh7757_eth1_device = { static struct platform_device sh7757_eth1_device = {
...@@ -98,10 +116,173 @@ static struct platform_device sh7757_eth1_device = { ...@@ -98,10 +116,173 @@ static struct platform_device sh7757_eth1_device = {
}, },
}; };
static void sh7757_eth_giga_set_mdio_gate(unsigned long addr)
{
if ((addr & 0x00000fff) < 0x0800) {
gpio_set_value(GPIO_PTT4, 1);
writel(readl(GBECONT) & ~GBECONT_RMII0, GBECONT);
} else {
gpio_set_value(GPIO_PTT4, 0);
writel(readl(GBECONT) & ~GBECONT_RMII1, GBECONT);
}
}
static struct resource sh_eth_giga0_resources[] = {
{
.start = 0xfee00000,
.end = 0xfee007ff,
.flags = IORESOURCE_MEM,
}, {
/* TSU */
.start = 0xfee01800,
.end = 0xfee01fff,
.flags = IORESOURCE_MEM,
}, {
.start = 315,
.end = 315,
.flags = IORESOURCE_IRQ,
},
};
static struct sh_eth_plat_data sh7757_eth_giga0_pdata = {
.phy = 18,
.edmac_endian = EDMAC_LITTLE_ENDIAN,
.register_type = SH_ETH_REG_GIGABIT,
.set_mdio_gate = sh7757_eth_giga_set_mdio_gate,
.phy_interface = PHY_INTERFACE_MODE_RGMII_ID,
};
static struct platform_device sh7757_eth_giga0_device = {
.name = "sh-eth",
.resource = sh_eth_giga0_resources,
.id = 2,
.num_resources = ARRAY_SIZE(sh_eth_giga0_resources),
.dev = {
.platform_data = &sh7757_eth_giga0_pdata,
},
};
static struct resource sh_eth_giga1_resources[] = {
{
.start = 0xfee00800,
.end = 0xfee00fff,
.flags = IORESOURCE_MEM,
}, {
.start = 316,
.end = 316,
.flags = IORESOURCE_IRQ,
},
};
static struct sh_eth_plat_data sh7757_eth_giga1_pdata = {
.phy = 19,
.edmac_endian = EDMAC_LITTLE_ENDIAN,
.register_type = SH_ETH_REG_GIGABIT,
.set_mdio_gate = sh7757_eth_giga_set_mdio_gate,
.phy_interface = PHY_INTERFACE_MODE_RGMII_ID,
};
static struct platform_device sh7757_eth_giga1_device = {
.name = "sh-eth",
.resource = sh_eth_giga1_resources,
.id = 3,
.num_resources = ARRAY_SIZE(sh_eth_giga1_resources),
.dev = {
.platform_data = &sh7757_eth_giga1_pdata,
},
};
/* SH_MMCIF */
static struct resource sh_mmcif_resources[] = {
[0] = {
.start = 0xffcb0000,
.end = 0xffcb00ff,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = 211,
.flags = IORESOURCE_IRQ,
},
[2] = {
.start = 212,
.flags = IORESOURCE_IRQ,
},
};
static struct sh_mmcif_dma sh7757lcr_mmcif_dma = {
.chan_priv_tx = SHDMA_SLAVE_MMCIF_TX,
.chan_priv_rx = SHDMA_SLAVE_MMCIF_RX,
};
static struct sh_mmcif_plat_data sh_mmcif_plat = {
.dma = &sh7757lcr_mmcif_dma,
.sup_pclk = 0x0f,
.caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
.ocr = MMC_VDD_32_33 | MMC_VDD_33_34,
};
static struct platform_device sh_mmcif_device = {
.name = "sh_mmcif",
.id = 0,
.dev = {
.platform_data = &sh_mmcif_plat,
},
.num_resources = ARRAY_SIZE(sh_mmcif_resources),
.resource = sh_mmcif_resources,
};
/* SDHI0 */
static struct sh_mobile_sdhi_info sdhi_info = {
.dma_slave_tx = SHDMA_SLAVE_SDHI_TX,
.dma_slave_rx = SHDMA_SLAVE_SDHI_RX,
.tmio_caps = MMC_CAP_SD_HIGHSPEED,
};
static struct resource sdhi_resources[] = {
[0] = {
.start = 0xffe50000,
.end = 0xffe501ff,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = 20,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device sdhi_device = {
.name = "sh_mobile_sdhi",
.num_resources = ARRAY_SIZE(sdhi_resources),
.resource = sdhi_resources,
.id = 0,
.dev = {
.platform_data = &sdhi_info,
},
};
static struct platform_device *sh7757lcr_devices[] __initdata = { static struct platform_device *sh7757lcr_devices[] __initdata = {
&heartbeat_device, &heartbeat_device,
&sh7757_eth0_device, &sh7757_eth0_device,
&sh7757_eth1_device, &sh7757_eth1_device,
&sh7757_eth_giga0_device,
&sh7757_eth_giga1_device,
&sh_mmcif_device,
&sdhi_device,
};
static struct flash_platform_data spi_flash_data = {
.name = "m25p80",
.type = "m25px64",
};
static struct spi_board_info spi_board_info[] = {
{
.modalias = "m25p80",
.max_speed_hz = 25000000,
.bus_num = 0,
.chip_select = 1,
.platform_data = &spi_flash_data,
},
}; };
static int __init sh7757lcr_devices_setup(void) static int __init sh7757lcr_devices_setup(void)
...@@ -332,6 +513,10 @@ static int __init sh7757lcr_devices_setup(void) ...@@ -332,6 +513,10 @@ static int __init sh7757lcr_devices_setup(void)
gpio_request(GPIO_PTT5, NULL); /* eMMC_PRST# */ gpio_request(GPIO_PTT5, NULL); /* eMMC_PRST# */
gpio_direction_output(GPIO_PTT5, 1); gpio_direction_output(GPIO_PTT5, 1);
/* register SPI device information */
spi_register_board_info(spi_board_info,
ARRAY_SIZE(spi_board_info));
/* General platform */ /* General platform */
return platform_add_devices(sh7757lcr_devices, return platform_add_devices(sh7757lcr_devices,
ARRAY_SIZE(sh7757lcr_devices)); ARRAY_SIZE(sh7757lcr_devices));
......
...@@ -142,6 +142,8 @@ static struct resource sh_eth_resources[] = { ...@@ -142,6 +142,8 @@ static struct resource sh_eth_resources[] = {
static struct sh_eth_plat_data sh_eth_plat = { static struct sh_eth_plat_data sh_eth_plat = {
.phy = 0x1f, /* SMSC LAN8700 */ .phy = 0x1f, /* SMSC LAN8700 */
.edmac_endian = EDMAC_LITTLE_ENDIAN, .edmac_endian = EDMAC_LITTLE_ENDIAN,
.register_type = SH_ETH_REG_FAST_SH4,
.phy_interface = PHY_INTERFACE_MODE_MII,
.ether_link_active_low = 1 .ether_link_active_low = 1
}; };
......
...@@ -74,6 +74,10 @@ static struct resource sh_eth_resources[] = { ...@@ -74,6 +74,10 @@ static struct resource sh_eth_resources[] = {
.start = 0xFEE00800, /* use eth1 */ .start = 0xFEE00800, /* use eth1 */
.end = 0xFEE00F7C - 1, .end = 0xFEE00F7C - 1,
.flags = IORESOURCE_MEM, .flags = IORESOURCE_MEM,
}, {
.start = 0xFEE01800, /* TSU */
.end = 0xFEE01FFF,
.flags = IORESOURCE_MEM,
}, { }, {
.start = 57, /* irq number */ .start = 57, /* irq number */
.flags = IORESOURCE_IRQ, .flags = IORESOURCE_IRQ,
...@@ -83,6 +87,8 @@ static struct resource sh_eth_resources[] = { ...@@ -83,6 +87,8 @@ static struct resource sh_eth_resources[] = {
static struct sh_eth_plat_data sh7763_eth_pdata = { static struct sh_eth_plat_data sh7763_eth_pdata = {
.phy = 1, .phy = 1,
.edmac_endian = EDMAC_LITTLE_ENDIAN, .edmac_endian = EDMAC_LITTLE_ENDIAN,
.register_type = SH_ETH_REG_GIGABIT,
.phy_interface = PHY_INTERFACE_MODE_MII,
}; };
static struct platform_device sh7763rdp_eth_device = { static struct platform_device sh7763rdp_eth_device = {
......
...@@ -11,6 +11,8 @@ targets := vmlinux vmlinux.bin vmlinux.bin.gz \ ...@@ -11,6 +11,8 @@ targets := vmlinux vmlinux.bin vmlinux.bin.gz \
OBJECTS = $(obj)/head_$(BITS).o $(obj)/misc.o $(obj)/cache.o OBJECTS = $(obj)/head_$(BITS).o $(obj)/misc.o $(obj)/cache.o
GCOV_PROFILE := n
# #
# IMAGE_OFFSET is the load offset of the compression loader # IMAGE_OFFSET is the load offset of the compression loader
# #
......
...@@ -38,7 +38,15 @@ CONFIG_IPV6=y ...@@ -38,7 +38,15 @@ CONFIG_IPV6=y
# CONFIG_WIRELESS is not set # CONFIG_WIRELESS is not set
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
# CONFIG_FW_LOADER is not set # CONFIG_FW_LOADER is not set
CONFIG_MTD=y
CONFIG_MTD_CONCAT=y
CONFIG_MTD_PARTITIONS=y
CONFIG_MTD_CHAR=y
CONFIG_MTD_BLOCK=y
CONFIG_MTD_M25P80=y
CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM=y
CONFIG_SCSI=y
CONFIG_BLK_DEV_SD=y
CONFIG_NETDEVICES=y CONFIG_NETDEVICES=y
CONFIG_VITESSE_PHY=y CONFIG_VITESSE_PHY=y
CONFIG_NET_ETHERNET=y CONFIG_NET_ETHERNET=y
...@@ -53,8 +61,17 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=3 ...@@ -53,8 +61,17 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=3
CONFIG_SERIAL_SH_SCI_CONSOLE=y CONFIG_SERIAL_SH_SCI_CONSOLE=y
# CONFIG_LEGACY_PTYS is not set # CONFIG_LEGACY_PTYS is not set
# CONFIG_HW_RANDOM is not set # CONFIG_HW_RANDOM is not set
CONFIG_SPI=y
CONFIG_SPI_SH=y
# CONFIG_HWMON is not set # CONFIG_HWMON is not set
# CONFIG_USB_SUPPORT is not set CONFIG_MFD_SH_MOBILE_SDHI=y
CONFIG_USB=y
CONFIG_USB_EHCI_HCD=y
CONFIG_USB_OHCI_HCD=y
CONFIG_USB_STORAGE=y
CONFIG_MMC=y
CONFIG_MMC_TMIO=y
CONFIG_MMC_SH_MMCIF=y
CONFIG_EXT2_FS=y CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y CONFIG_EXT3_FS=y
CONFIG_ISO9660_FS=y CONFIG_ISO9660_FS=y
......
/* /*
* Low-Level PCI Express Support for the SH7786 * Low-Level PCI Express Support for the SH7786
* *
* Copyright (C) 2009 - 2010 Paul Mundt * Copyright (C) 2009 - 2011 Paul Mundt
* *
* This file is subject to the terms and conditions of the GNU General Public * 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 * License. See the file "COPYING" in the main directory of this archive
* for more details. * for more details.
*/ */
#define pr_fmt(fmt) "PCI: " fmt
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/async.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/clk.h> #include <linux/clk.h>
...@@ -31,7 +34,7 @@ static unsigned int nr_ports; ...@@ -31,7 +34,7 @@ static unsigned int nr_ports;
static struct sh7786_pcie_hwops { static struct sh7786_pcie_hwops {
int (*core_init)(void); int (*core_init)(void);
int (*port_init_hw)(struct sh7786_pcie_port *port); async_func_ptr *port_init_hw;
} *sh7786_pcie_hwops; } *sh7786_pcie_hwops;
static struct resource sh7786_pci0_resources[] = { static struct resource sh7786_pci0_resources[] = {
...@@ -474,8 +477,9 @@ static int __init sh7786_pcie_core_init(void) ...@@ -474,8 +477,9 @@ static int __init sh7786_pcie_core_init(void)
return test_mode_pin(MODE_PIN12) ? 3 : 2; return test_mode_pin(MODE_PIN12) ? 3 : 2;
} }
static int __init sh7786_pcie_init_hw(struct sh7786_pcie_port *port) static void __init sh7786_pcie_init_hw(void *data, async_cookie_t cookie)
{ {
struct sh7786_pcie_port *port = data;
int ret; int ret;
/* /*
...@@ -488,18 +492,30 @@ static int __init sh7786_pcie_init_hw(struct sh7786_pcie_port *port) ...@@ -488,18 +492,30 @@ static int __init sh7786_pcie_init_hw(struct sh7786_pcie_port *port)
* Setup clocks, needed both for PHY and PCIe registers. * Setup clocks, needed both for PHY and PCIe registers.
*/ */
ret = pcie_clk_init(port); ret = pcie_clk_init(port);
if (unlikely(ret < 0)) if (unlikely(ret < 0)) {
return ret; pr_err("clock initialization failed for port#%d\n",
port->index);
return;
}
ret = phy_init(port); ret = phy_init(port);
if (unlikely(ret < 0)) if (unlikely(ret < 0)) {
return ret; pr_err("phy initialization failed for port#%d\n",
port->index);
return;
}
ret = pcie_init(port); ret = pcie_init(port);
if (unlikely(ret < 0)) if (unlikely(ret < 0)) {
return ret; pr_err("core initialization failed for port#%d\n",
port->index);
return;
}
return register_pci_controller(port->hose); /* In the interest of preserving device ordering, synchronize */
async_synchronize_cookie(cookie);
register_pci_controller(port->hose);
} }
static struct sh7786_pcie_hwops sh7786_65nm_pcie_hwops __initdata = { static struct sh7786_pcie_hwops sh7786_65nm_pcie_hwops __initdata = {
...@@ -510,7 +526,7 @@ static struct sh7786_pcie_hwops sh7786_65nm_pcie_hwops __initdata = { ...@@ -510,7 +526,7 @@ static struct sh7786_pcie_hwops sh7786_65nm_pcie_hwops __initdata = {
static int __init sh7786_pcie_init(void) static int __init sh7786_pcie_init(void)
{ {
struct clk *platclk; struct clk *platclk;
int ret = 0, i; int i;
printk(KERN_NOTICE "PCI: Starting initialization.\n"); printk(KERN_NOTICE "PCI: Starting initialization.\n");
...@@ -552,14 +568,10 @@ static int __init sh7786_pcie_init(void) ...@@ -552,14 +568,10 @@ static int __init sh7786_pcie_init(void)
port->hose = sh7786_pci_channels + i; port->hose = sh7786_pci_channels + i;
port->hose->io_map_base = port->hose->resources[0].start; port->hose->io_map_base = port->hose->resources[0].start;
ret |= sh7786_pcie_hwops->port_init_hw(port); async_schedule(sh7786_pcie_hwops->port_init_hw, port);
} }
if (unlikely(ret)) { async_synchronize_full();
clk_disable(platclk);
clk_put(platclk);
return ret;
}
return 0; return 0;
} }
......
...@@ -369,8 +369,11 @@ ...@@ -369,8 +369,11 @@
#define __NR_recvmsg 356 #define __NR_recvmsg 356
#define __NR_recvmmsg 357 #define __NR_recvmmsg 357
#define __NR_accept4 358 #define __NR_accept4 358
#define __NR_name_to_handle_at 359
#define __NR_open_by_handle_at 360
#define __NR_clock_adjtime 361
#define NR_syscalls 359 #define NR_syscalls 362
#ifdef __KERNEL__ #ifdef __KERNEL__
......
...@@ -390,10 +390,13 @@ ...@@ -390,10 +390,13 @@
#define __NR_fanotify_init 367 #define __NR_fanotify_init 367
#define __NR_fanotify_mark 368 #define __NR_fanotify_mark 368
#define __NR_prlimit64 369 #define __NR_prlimit64 369
#define __NR_name_to_handle_at 370
#define __NR_open_by_handle_at 371
#define __NR_clock_adjtime 372
#ifdef __KERNEL__ #ifdef __KERNEL__
#define NR_syscalls 370 #define NR_syscalls 373
#define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_IPC_PARSE_VERSION
#define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_OLD_READDIR
......
...@@ -40,6 +40,11 @@ ...@@ -40,6 +40,11 @@
#define CHCR_TS_LOW_SHIFT 3 #define CHCR_TS_LOW_SHIFT 3
#define CHCR_TS_HIGH_MASK 0 #define CHCR_TS_HIGH_MASK 0
#define CHCR_TS_HIGH_SHIFT 0 #define CHCR_TS_HIGH_SHIFT 0
#elif defined(CONFIG_CPU_SUBTYPE_SH7757)
#define CHCR_TS_LOW_MASK 0x00000018
#define CHCR_TS_LOW_SHIFT 3
#define CHCR_TS_HIGH_MASK 0x00100000
#define CHCR_TS_HIGH_SHIFT (20 - 2) /* 2 bits for shifted low TS */
#elif defined(CONFIG_CPU_SUBTYPE_SH7780) #elif defined(CONFIG_CPU_SUBTYPE_SH7780)
#define CHCR_TS_LOW_MASK 0x00000018 #define CHCR_TS_LOW_MASK 0x00000018
#define CHCR_TS_LOW_SHIFT 3 #define CHCR_TS_LOW_SHIFT 3
......
...@@ -251,4 +251,36 @@ enum { ...@@ -251,4 +251,36 @@ enum {
GPIO_FN_ON_DQ3, GPIO_FN_ON_DQ2, GPIO_FN_ON_DQ1, GPIO_FN_ON_DQ0, GPIO_FN_ON_DQ3, GPIO_FN_ON_DQ2, GPIO_FN_ON_DQ1, GPIO_FN_ON_DQ0,
}; };
enum {
SHDMA_SLAVE_SDHI_TX,
SHDMA_SLAVE_SDHI_RX,
SHDMA_SLAVE_MMCIF_TX,
SHDMA_SLAVE_MMCIF_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_RIIC0_TX,
SHDMA_SLAVE_RIIC0_RX,
SHDMA_SLAVE_RIIC1_TX,
SHDMA_SLAVE_RIIC1_RX,
SHDMA_SLAVE_RIIC2_TX,
SHDMA_SLAVE_RIIC2_RX,
SHDMA_SLAVE_RIIC3_TX,
SHDMA_SLAVE_RIIC3_RX,
SHDMA_SLAVE_RIIC4_TX,
SHDMA_SLAVE_RIIC4_RX,
SHDMA_SLAVE_RIIC5_TX,
SHDMA_SLAVE_RIIC5_RX,
SHDMA_SLAVE_RIIC6_TX,
SHDMA_SLAVE_RIIC6_RX,
SHDMA_SLAVE_RIIC7_TX,
SHDMA_SLAVE_RIIC7_RX,
SHDMA_SLAVE_RIIC8_TX,
SHDMA_SLAVE_RIIC8_RX,
SHDMA_SLAVE_RIIC9_TX,
SHDMA_SLAVE_RIIC9_RX,
};
#endif /* __ASM_SH7757_H__ */ #endif /* __ASM_SH7757_H__ */
...@@ -77,9 +77,10 @@ struct clk div4_clks[DIV4_NR] = { ...@@ -77,9 +77,10 @@ struct clk div4_clks[DIV4_NR] = {
#define MSTPCR0 0xffc80030 #define MSTPCR0 0xffc80030
#define MSTPCR1 0xffc80034 #define MSTPCR1 0xffc80034
#define MSTPCR2 0xffc10028
enum { MSTP004, MSTP000, MSTP114, MSTP113, MSTP112, enum { MSTP004, MSTP000, MSTP114, MSTP113, MSTP112,
MSTP111, MSTP110, MSTP103, MSTP102, MSTP111, MSTP110, MSTP103, MSTP102, MSTP220,
MSTP_NR }; MSTP_NR };
static struct clk mstp_clks[MSTP_NR] = { static struct clk mstp_clks[MSTP_NR] = {
...@@ -95,6 +96,9 @@ static struct clk mstp_clks[MSTP_NR] = { ...@@ -95,6 +96,9 @@ static struct clk mstp_clks[MSTP_NR] = {
[MSTP110] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 10, 0), [MSTP110] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 10, 0),
[MSTP103] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 3, 0), [MSTP103] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 3, 0),
[MSTP102] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 2, 0), [MSTP102] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 2, 0),
/* MSTPCR2 */
[MSTP220] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR2, 20, 0),
}; };
#define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk } #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
...@@ -140,6 +144,7 @@ static struct clk_lookup lookups[] = { ...@@ -140,6 +144,7 @@ static struct clk_lookup lookups[] = {
.clk = &mstp_clks[MSTP110], .clk = &mstp_clks[MSTP110],
}, },
CLKDEV_CON_ID("usb0", &mstp_clks[MSTP102]), CLKDEV_CON_ID("usb0", &mstp_clks[MSTP102]),
CLKDEV_CON_ID("mmc0", &mstp_clks[MSTP220]),
}; };
int __init arch_clk_init(void) int __init arch_clk_init(void)
......
/* /*
* SH7757 Setup * SH7757 Setup
* *
* Copyright (C) 2009 Renesas Solutions Corp. * Copyright (C) 2009, 2011 Renesas Solutions Corp.
* *
* based on setup-sh7785.c : Copyright (C) 2007 Paul Mundt * based on setup-sh7785.c : Copyright (C) 2007 Paul Mundt
* *
...@@ -16,6 +16,10 @@ ...@@ -16,6 +16,10 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/sh_timer.h> #include <linux/sh_timer.h>
#include <linux/sh_dma.h>
#include <cpu/dma-register.h>
#include <cpu/sh7757.h>
static struct plat_sci_port scif2_platform_data = { static struct plat_sci_port scif2_platform_data = {
.mapbase = 0xfe4b0000, /* SCIF2 */ .mapbase = 0xfe4b0000, /* SCIF2 */
...@@ -124,12 +128,548 @@ static struct platform_device tmu1_device = { ...@@ -124,12 +128,548 @@ static struct platform_device tmu1_device = {
.num_resources = ARRAY_SIZE(tmu1_resources), .num_resources = ARRAY_SIZE(tmu1_resources),
}; };
static struct resource spi0_resources[] = {
[0] = {
.start = 0xfe002000,
.end = 0xfe0020ff,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = 86,
.flags = IORESOURCE_IRQ,
},
};
/* DMA */
static const struct sh_dmae_slave_config sh7757_dmae0_slaves[] = {
{
.slave_id = SHDMA_SLAVE_SDHI_TX,
.addr = 0x1fe50030,
.chcr = SM_INC | 0x800 | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_16BIT),
.mid_rid = 0xc5,
},
{
.slave_id = SHDMA_SLAVE_SDHI_RX,
.addr = 0x1fe50030,
.chcr = DM_INC | 0x800 | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_16BIT),
.mid_rid = 0xc6,
},
{
.slave_id = SHDMA_SLAVE_MMCIF_TX,
.addr = 0x1fcb0034,
.chcr = SM_INC | 0x800 | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_32BIT),
.mid_rid = 0xd3,
},
{
.slave_id = SHDMA_SLAVE_MMCIF_RX,
.addr = 0x1fcb0034,
.chcr = DM_INC | 0x800 | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_32BIT),
.mid_rid = 0xd7,
},
};
static const struct sh_dmae_slave_config sh7757_dmae1_slaves[] = {
{
.slave_id = SHDMA_SLAVE_SCIF2_TX,
.addr = 0x1f4b000c,
.chcr = SM_INC | 0x800 | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x21,
},
{
.slave_id = SHDMA_SLAVE_SCIF2_RX,
.addr = 0x1f4b0014,
.chcr = SM_INC | 0x800 | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x22,
},
{
.slave_id = SHDMA_SLAVE_SCIF3_TX,
.addr = 0x1f4c000c,
.chcr = SM_INC | 0x800 | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x29,
},
{
.slave_id = SHDMA_SLAVE_SCIF3_RX,
.addr = 0x1f4c0014,
.chcr = SM_INC | 0x800 | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x2a,
},
{
.slave_id = SHDMA_SLAVE_SCIF4_TX,
.addr = 0x1f4d000c,
.chcr = SM_INC | 0x800 | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x41,
},
{
.slave_id = SHDMA_SLAVE_SCIF4_RX,
.addr = 0x1f4d0014,
.chcr = SM_INC | 0x800 | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x42,
},
};
static const struct sh_dmae_slave_config sh7757_dmae2_slaves[] = {
{
.slave_id = SHDMA_SLAVE_RIIC0_TX,
.addr = 0x1e500012,
.chcr = SM_INC | 0x800 | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x21,
},
{
.slave_id = SHDMA_SLAVE_RIIC0_RX,
.addr = 0x1e500013,
.chcr = SM_INC | 0x800 | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x22,
},
{
.slave_id = SHDMA_SLAVE_RIIC1_TX,
.addr = 0x1e510012,
.chcr = SM_INC | 0x800 | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x29,
},
{
.slave_id = SHDMA_SLAVE_RIIC1_RX,
.addr = 0x1e510013,
.chcr = SM_INC | 0x800 | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x2a,
},
{
.slave_id = SHDMA_SLAVE_RIIC2_TX,
.addr = 0x1e520012,
.chcr = SM_INC | 0x800 | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0xa1,
},
{
.slave_id = SHDMA_SLAVE_RIIC2_RX,
.addr = 0x1e520013,
.chcr = SM_INC | 0x800 | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0xa2,
},
{
.slave_id = SHDMA_SLAVE_RIIC3_TX,
.addr = 0x1e530012,
.chcr = SM_INC | 0x800 | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0xab,
},
{
.slave_id = SHDMA_SLAVE_RIIC3_RX,
.addr = 0x1e530013,
.chcr = SM_INC | 0x800 | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0xaf,
},
{
.slave_id = SHDMA_SLAVE_RIIC4_TX,
.addr = 0x1e540012,
.chcr = SM_INC | 0x800 | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0xc1,
},
{
.slave_id = SHDMA_SLAVE_RIIC4_RX,
.addr = 0x1e540013,
.chcr = SM_INC | 0x800 | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0xc2,
},
};
static const struct sh_dmae_slave_config sh7757_dmae3_slaves[] = {
{
.slave_id = SHDMA_SLAVE_RIIC5_TX,
.addr = 0x1e550012,
.chcr = SM_INC | 0x800 | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x21,
},
{
.slave_id = SHDMA_SLAVE_RIIC5_RX,
.addr = 0x1e550013,
.chcr = SM_INC | 0x800 | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x22,
},
{
.slave_id = SHDMA_SLAVE_RIIC6_TX,
.addr = 0x1e560012,
.chcr = SM_INC | 0x800 | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x29,
},
{
.slave_id = SHDMA_SLAVE_RIIC6_RX,
.addr = 0x1e560013,
.chcr = SM_INC | 0x800 | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x2a,
},
{
.slave_id = SHDMA_SLAVE_RIIC7_TX,
.addr = 0x1e570012,
.chcr = SM_INC | 0x800 | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x41,
},
{
.slave_id = SHDMA_SLAVE_RIIC7_RX,
.addr = 0x1e570013,
.chcr = SM_INC | 0x800 | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x42,
},
{
.slave_id = SHDMA_SLAVE_RIIC8_TX,
.addr = 0x1e580012,
.chcr = SM_INC | 0x800 | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x45,
},
{
.slave_id = SHDMA_SLAVE_RIIC8_RX,
.addr = 0x1e580013,
.chcr = SM_INC | 0x800 | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x46,
},
{
.slave_id = SHDMA_SLAVE_RIIC9_TX,
.addr = 0x1e590012,
.chcr = SM_INC | 0x800 | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x51,
},
{
.slave_id = SHDMA_SLAVE_RIIC9_RX,
.addr = 0x1e590013,
.chcr = SM_INC | 0x800 | 0x40000000 |
TS_INDEX2VAL(XMIT_SZ_8BIT),
.mid_rid = 0x52,
},
};
static const struct sh_dmae_channel sh7757_dmae_channels[] = {
{
.offset = 0,
.dmars = 0,
.dmars_bit = 0,
}, {
.offset = 0x10,
.dmars = 0,
.dmars_bit = 8,
}, {
.offset = 0x20,
.dmars = 4,
.dmars_bit = 0,
}, {
.offset = 0x30,
.dmars = 4,
.dmars_bit = 8,
}, {
.offset = 0x50,
.dmars = 8,
.dmars_bit = 0,
}, {
.offset = 0x60,
.dmars = 8,
.dmars_bit = 8,
}
};
static const unsigned int ts_shift[] = TS_SHIFT;
static struct sh_dmae_pdata dma0_platform_data = {
.slave = sh7757_dmae0_slaves,
.slave_num = ARRAY_SIZE(sh7757_dmae0_slaves),
.channel = sh7757_dmae_channels,
.channel_num = ARRAY_SIZE(sh7757_dmae_channels),
.ts_low_shift = CHCR_TS_LOW_SHIFT,
.ts_low_mask = CHCR_TS_LOW_MASK,
.ts_high_shift = CHCR_TS_HIGH_SHIFT,
.ts_high_mask = CHCR_TS_HIGH_MASK,
.ts_shift = ts_shift,
.ts_shift_num = ARRAY_SIZE(ts_shift),
.dmaor_init = DMAOR_INIT,
};
static struct sh_dmae_pdata dma1_platform_data = {
.slave = sh7757_dmae1_slaves,
.slave_num = ARRAY_SIZE(sh7757_dmae1_slaves),
.channel = sh7757_dmae_channels,
.channel_num = ARRAY_SIZE(sh7757_dmae_channels),
.ts_low_shift = CHCR_TS_LOW_SHIFT,
.ts_low_mask = CHCR_TS_LOW_MASK,
.ts_high_shift = CHCR_TS_HIGH_SHIFT,
.ts_high_mask = CHCR_TS_HIGH_MASK,
.ts_shift = ts_shift,
.ts_shift_num = ARRAY_SIZE(ts_shift),
.dmaor_init = DMAOR_INIT,
};
static struct sh_dmae_pdata dma2_platform_data = {
.slave = sh7757_dmae2_slaves,
.slave_num = ARRAY_SIZE(sh7757_dmae2_slaves),
.channel = sh7757_dmae_channels,
.channel_num = ARRAY_SIZE(sh7757_dmae_channels),
.ts_low_shift = CHCR_TS_LOW_SHIFT,
.ts_low_mask = CHCR_TS_LOW_MASK,
.ts_high_shift = CHCR_TS_HIGH_SHIFT,
.ts_high_mask = CHCR_TS_HIGH_MASK,
.ts_shift = ts_shift,
.ts_shift_num = ARRAY_SIZE(ts_shift),
.dmaor_init = DMAOR_INIT,
};
static struct sh_dmae_pdata dma3_platform_data = {
.slave = sh7757_dmae3_slaves,
.slave_num = ARRAY_SIZE(sh7757_dmae3_slaves),
.channel = sh7757_dmae_channels,
.channel_num = ARRAY_SIZE(sh7757_dmae_channels),
.ts_low_shift = CHCR_TS_LOW_SHIFT,
.ts_low_mask = CHCR_TS_LOW_MASK,
.ts_high_shift = CHCR_TS_HIGH_SHIFT,
.ts_high_mask = CHCR_TS_HIGH_MASK,
.ts_shift = ts_shift,
.ts_shift_num = ARRAY_SIZE(ts_shift),
.dmaor_init = DMAOR_INIT,
};
/* channel 0 to 5 */
static struct resource sh7757_dmae0_resources[] = {
[0] = {
/* Channel registers and DMAOR */
.start = 0xff608020,
.end = 0xff60808f,
.flags = IORESOURCE_MEM,
},
[1] = {
/* DMARSx */
.start = 0xff609000,
.end = 0xff60900b,
.flags = IORESOURCE_MEM,
},
{
.start = 34,
.end = 34,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
},
};
/* channel 6 to 11 */
static struct resource sh7757_dmae1_resources[] = {
[0] = {
/* Channel registers and DMAOR */
.start = 0xff618020,
.end = 0xff61808f,
.flags = IORESOURCE_MEM,
},
[1] = {
/* DMARSx */
.start = 0xff619000,
.end = 0xff61900b,
.flags = IORESOURCE_MEM,
},
{
/* DMA error */
.start = 34,
.end = 34,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
},
{
/* IRQ for channels 4 */
.start = 46,
.end = 46,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
},
{
/* IRQ for channels 5 */
.start = 46,
.end = 46,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
},
{
/* IRQ for channels 6 */
.start = 88,
.end = 88,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
},
{
/* IRQ for channels 7 */
.start = 88,
.end = 88,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
},
{
/* IRQ for channels 8 */
.start = 88,
.end = 88,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
},
{
/* IRQ for channels 9 */
.start = 88,
.end = 88,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
},
{
/* IRQ for channels 10 */
.start = 88,
.end = 88,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
},
{
/* IRQ for channels 11 */
.start = 88,
.end = 88,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
},
};
/* channel 12 to 17 */
static struct resource sh7757_dmae2_resources[] = {
[0] = {
/* Channel registers and DMAOR */
.start = 0xff708020,
.end = 0xff70808f,
.flags = IORESOURCE_MEM,
},
[1] = {
/* DMARSx */
.start = 0xff709000,
.end = 0xff70900b,
.flags = IORESOURCE_MEM,
},
{
/* DMA error */
.start = 323,
.end = 323,
.flags = IORESOURCE_IRQ,
},
{
/* IRQ for channels 12 to 16 */
.start = 272,
.end = 276,
.flags = IORESOURCE_IRQ,
},
{
/* IRQ for channel 17 */
.start = 279,
.end = 279,
.flags = IORESOURCE_IRQ,
},
};
/* channel 18 to 23 */
static struct resource sh7757_dmae3_resources[] = {
[0] = {
/* Channel registers and DMAOR */
.start = 0xff718020,
.end = 0xff71808f,
.flags = IORESOURCE_MEM,
},
[1] = {
/* DMARSx */
.start = 0xff719000,
.end = 0xff71900b,
.flags = IORESOURCE_MEM,
},
{
/* DMA error */
.start = 324,
.end = 324,
.flags = IORESOURCE_IRQ,
},
{
/* IRQ for channels 18 to 22 */
.start = 280,
.end = 284,
.flags = IORESOURCE_IRQ,
},
{
/* IRQ for channel 23 */
.start = 288,
.end = 288,
.flags = IORESOURCE_IRQ,
},
};
static struct platform_device dma0_device = {
.name = "sh-dma-engine",
.id = 0,
.resource = sh7757_dmae0_resources,
.num_resources = ARRAY_SIZE(sh7757_dmae0_resources),
.dev = {
.platform_data = &dma0_platform_data,
},
};
static struct platform_device dma1_device = {
.name = "sh-dma-engine",
.id = 1,
.resource = sh7757_dmae1_resources,
.num_resources = ARRAY_SIZE(sh7757_dmae1_resources),
.dev = {
.platform_data = &dma1_platform_data,
},
};
static struct platform_device dma2_device = {
.name = "sh-dma-engine",
.id = 2,
.resource = sh7757_dmae2_resources,
.num_resources = ARRAY_SIZE(sh7757_dmae2_resources),
.dev = {
.platform_data = &dma2_platform_data,
},
};
static struct platform_device dma3_device = {
.name = "sh-dma-engine",
.id = 3,
.resource = sh7757_dmae3_resources,
.num_resources = ARRAY_SIZE(sh7757_dmae3_resources),
.dev = {
.platform_data = &dma3_platform_data,
},
};
static struct platform_device spi0_device = {
.name = "sh_spi",
.id = 0,
.dev = {
.dma_mask = NULL,
.coherent_dma_mask = 0xffffffff,
},
.num_resources = ARRAY_SIZE(spi0_resources),
.resource = spi0_resources,
};
static struct platform_device *sh7757_devices[] __initdata = { static struct platform_device *sh7757_devices[] __initdata = {
&scif2_device, &scif2_device,
&scif3_device, &scif3_device,
&scif4_device, &scif4_device,
&tmu0_device, &tmu0_device,
&tmu1_device, &tmu1_device,
&dma0_device,
&dma1_device,
&dma2_device,
&dma3_device,
&spi0_device,
}; };
static int __init sh7757_devices_setup(void) static int __init sh7757_devices_setup(void)
......
...@@ -75,7 +75,7 @@ void sh_mobile_setup_cpuidle(void) ...@@ -75,7 +75,7 @@ void sh_mobile_setup_cpuidle(void)
i = CPUIDLE_DRIVER_STATE_START; i = CPUIDLE_DRIVER_STATE_START;
state = &dev->states[i++]; state = &dev->states[i++];
snprintf(state->name, CPUIDLE_NAME_LEN, "C0"); snprintf(state->name, CPUIDLE_NAME_LEN, "C1");
strncpy(state->desc, "SuperH Sleep Mode", CPUIDLE_DESC_LEN); strncpy(state->desc, "SuperH Sleep Mode", CPUIDLE_DESC_LEN);
state->exit_latency = 1; state->exit_latency = 1;
state->target_residency = 1 * 2; state->target_residency = 1 * 2;
...@@ -88,7 +88,7 @@ void sh_mobile_setup_cpuidle(void) ...@@ -88,7 +88,7 @@ void sh_mobile_setup_cpuidle(void)
if (sh_mobile_sleep_supported & SUSP_SH_SF) { if (sh_mobile_sleep_supported & SUSP_SH_SF) {
state = &dev->states[i++]; state = &dev->states[i++];
snprintf(state->name, CPUIDLE_NAME_LEN, "C1"); snprintf(state->name, CPUIDLE_NAME_LEN, "C2");
strncpy(state->desc, "SuperH Sleep Mode [SF]", strncpy(state->desc, "SuperH Sleep Mode [SF]",
CPUIDLE_DESC_LEN); CPUIDLE_DESC_LEN);
state->exit_latency = 100; state->exit_latency = 100;
...@@ -101,7 +101,7 @@ void sh_mobile_setup_cpuidle(void) ...@@ -101,7 +101,7 @@ void sh_mobile_setup_cpuidle(void)
if (sh_mobile_sleep_supported & SUSP_SH_STANDBY) { if (sh_mobile_sleep_supported & SUSP_SH_STANDBY) {
state = &dev->states[i++]; state = &dev->states[i++];
snprintf(state->name, CPUIDLE_NAME_LEN, "C2"); snprintf(state->name, CPUIDLE_NAME_LEN, "C3");
strncpy(state->desc, "SuperH Mobile Standby Mode [SF]", strncpy(state->desc, "SuperH Mobile Standby Mode [SF]",
CPUIDLE_DESC_LEN); CPUIDLE_DESC_LEN);
state->exit_latency = 2300; state->exit_latency = 2300;
......
...@@ -34,9 +34,9 @@ void ack_bad_irq(unsigned int irq) ...@@ -34,9 +34,9 @@ void ack_bad_irq(unsigned int irq)
#if defined(CONFIG_PROC_FS) #if defined(CONFIG_PROC_FS)
/* /*
* /proc/interrupts printing: * /proc/interrupts printing for arch specific interrupts
*/ */
static int show_other_interrupts(struct seq_file *p, int prec) int arch_show_interrupts(struct seq_file *p, int prec)
{ {
int j; int j;
...@@ -49,63 +49,6 @@ static int show_other_interrupts(struct seq_file *p, int prec) ...@@ -49,63 +49,6 @@ static int show_other_interrupts(struct seq_file *p, int prec)
return 0; return 0;
} }
int show_interrupts(struct seq_file *p, void *v)
{
unsigned long flags, any_count = 0;
int i = *(loff_t *)v, j, prec;
struct irqaction *action;
struct irq_desc *desc;
struct irq_data *data;
struct irq_chip *chip;
if (i > nr_irqs)
return 0;
for (prec = 3, j = 1000; prec < 10 && j <= nr_irqs; ++prec)
j *= 10;
if (i == nr_irqs)
return show_other_interrupts(p, prec);
if (i == 0) {
seq_printf(p, "%*s", prec + 8, "");
for_each_online_cpu(j)
seq_printf(p, "CPU%-8d", j);
seq_putc(p, '\n');
}
desc = irq_to_desc(i);
if (!desc)
return 0;
data = irq_get_irq_data(i);
chip = irq_data_get_irq_chip(data);
raw_spin_lock_irqsave(&desc->lock, flags);
for_each_online_cpu(j)
any_count |= kstat_irqs_cpu(i, j);
action = desc->action;
if (!action && !any_count)
goto out;
seq_printf(p, "%*d: ", prec, i);
for_each_online_cpu(j)
seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
seq_printf(p, " %14s", chip->name);
seq_printf(p, "-%-8s", desc->name);
if (action) {
seq_printf(p, " %s", action->name);
while ((action = action->next) != NULL)
seq_printf(p, ", %s", action->name);
}
seq_putc(p, '\n');
out:
raw_spin_unlock_irqrestore(&desc->lock, flags);
return 0;
}
#endif #endif
#ifdef CONFIG_IRQSTACKS #ifdef CONFIG_IRQSTACKS
......
...@@ -376,3 +376,6 @@ ENTRY(sys_call_table) ...@@ -376,3 +376,6 @@ ENTRY(sys_call_table)
.long sys_recvmsg .long sys_recvmsg
.long sys_recvmmsg .long sys_recvmmsg
.long sys_accept4 .long sys_accept4
.long sys_name_to_handle_at
.long sys_open_by_handle_at /* 360 */
.long sys_clock_adjtime
...@@ -396,3 +396,6 @@ sys_call_table: ...@@ -396,3 +396,6 @@ sys_call_table:
.long sys_fanotify_init .long sys_fanotify_init
.long sys_fanotify_mark .long sys_fanotify_mark
.long sys_prlimit64 .long sys_prlimit64
.long sys_name_to_handle_at /* 370 */
.long sys_open_by_handle_at
.long sys_clock_adjtime
...@@ -42,6 +42,8 @@ obj-$(CONFIG_IOREMAP_FIXED) += ioremap_fixed.o ...@@ -42,6 +42,8 @@ obj-$(CONFIG_IOREMAP_FIXED) += ioremap_fixed.o
obj-$(CONFIG_UNCACHED_MAPPING) += uncached.o obj-$(CONFIG_UNCACHED_MAPPING) += uncached.o
obj-$(CONFIG_HAVE_SRAM_POOL) += sram.o obj-$(CONFIG_HAVE_SRAM_POOL) += sram.o
GCOV_PROFILE_pmb.o := n
# Special flags for fault_64.o. This puts restrictions on the number of # Special flags for fault_64.o. This puts restrictions on the number of
# caller-save registers that the compiler can target when building this file. # caller-save registers that the compiler can target when building this file.
# This is required because the code is called from a context in entry.S where # This is required because the code is called from a context in entry.S where
......
...@@ -47,7 +47,6 @@ ...@@ -47,7 +47,6 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/ctype.h> #include <linux/ctype.h>
#include <linux/err.h> #include <linux/err.h>
#include <linux/list.h>
#include <linux/dmaengine.h> #include <linux/dmaengine.h>
#include <linux/scatterlist.h> #include <linux/scatterlist.h>
#include <linux/slab.h> #include <linux/slab.h>
...@@ -65,11 +64,8 @@ ...@@ -65,11 +64,8 @@
struct sci_port { struct sci_port {
struct uart_port port; struct uart_port port;
/* Port type */ /* Platform configuration */
unsigned int type; struct plat_sci_port *cfg;
/* Port IRQs: ERI, RXI, TXI, BRI (optional) */
unsigned int irqs[SCIx_NR_IRQS];
/* Port enable callback */ /* Port enable callback */
void (*enable)(struct uart_port *port); void (*enable)(struct uart_port *port);
...@@ -81,26 +77,15 @@ struct sci_port { ...@@ -81,26 +77,15 @@ struct sci_port {
struct timer_list break_timer; struct timer_list break_timer;
int break_flag; int break_flag;
/* SCSCR initialization */
unsigned int scscr;
/* SCBRR calculation algo */
unsigned int scbrr_algo_id;
/* Interface clock */ /* Interface clock */
struct clk *iclk; struct clk *iclk;
/* Function clock */ /* Function clock */
struct clk *fclk; struct clk *fclk;
struct list_head node;
struct dma_chan *chan_tx; struct dma_chan *chan_tx;
struct dma_chan *chan_rx; struct dma_chan *chan_rx;
#ifdef CONFIG_SERIAL_SH_SCI_DMA #ifdef CONFIG_SERIAL_SH_SCI_DMA
struct device *dma_dev;
unsigned int slave_tx;
unsigned int slave_rx;
struct dma_async_tx_descriptor *desc_tx; struct dma_async_tx_descriptor *desc_tx;
struct dma_async_tx_descriptor *desc_rx[2]; struct dma_async_tx_descriptor *desc_rx[2];
dma_cookie_t cookie_tx; dma_cookie_t cookie_tx;
...@@ -117,16 +102,14 @@ struct sci_port { ...@@ -117,16 +102,14 @@ struct sci_port {
struct timer_list rx_timer; struct timer_list rx_timer;
unsigned int rx_timeout; unsigned int rx_timeout;
#endif #endif
};
struct sh_sci_priv { struct notifier_block freq_transition;
spinlock_t lock;
struct list_head ports;
struct notifier_block clk_nb;
}; };
/* Function prototypes */ /* Function prototypes */
static void sci_start_tx(struct uart_port *port);
static void sci_stop_tx(struct uart_port *port); static void sci_stop_tx(struct uart_port *port);
static void sci_start_rx(struct uart_port *port);
#define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS #define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS
...@@ -142,12 +125,6 @@ to_sci_port(struct uart_port *uart) ...@@ -142,12 +125,6 @@ to_sci_port(struct uart_port *uart)
#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_SH_SCI_CONSOLE) #if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_SH_SCI_CONSOLE)
#ifdef CONFIG_CONSOLE_POLL #ifdef CONFIG_CONSOLE_POLL
static inline void handle_error(struct uart_port *port)
{
/* Clear error flags */
sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
}
static int sci_poll_get_char(struct uart_port *port) static int sci_poll_get_char(struct uart_port *port)
{ {
unsigned short status; unsigned short status;
...@@ -156,7 +133,7 @@ static int sci_poll_get_char(struct uart_port *port) ...@@ -156,7 +133,7 @@ static int sci_poll_get_char(struct uart_port *port)
do { do {
status = sci_in(port, SCxSR); status = sci_in(port, SCxSR);
if (status & SCxSR_ERRORS(port)) { if (status & SCxSR_ERRORS(port)) {
handle_error(port); sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
continue; continue;
} }
break; break;
...@@ -475,7 +452,7 @@ static void sci_transmit_chars(struct uart_port *port) ...@@ -475,7 +452,7 @@ static void sci_transmit_chars(struct uart_port *port)
/* On SH3, SCIF may read end-of-break as a space->mark char */ /* On SH3, SCIF may read end-of-break as a space->mark char */
#define STEPFN(c) ({int __c = (c); (((__c-1)|(__c)) == -1); }) #define STEPFN(c) ({int __c = (c); (((__c-1)|(__c)) == -1); })
static inline void sci_receive_chars(struct uart_port *port) static void sci_receive_chars(struct uart_port *port)
{ {
struct sci_port *sci_port = to_sci_port(port); struct sci_port *sci_port = to_sci_port(port);
struct tty_struct *tty = port->state->port.tty; struct tty_struct *tty = port->state->port.tty;
...@@ -566,18 +543,20 @@ static inline void sci_receive_chars(struct uart_port *port) ...@@ -566,18 +543,20 @@ static inline void sci_receive_chars(struct uart_port *port)
} }
#define SCI_BREAK_JIFFIES (HZ/20) #define SCI_BREAK_JIFFIES (HZ/20)
/* The sci generates interrupts during the break,
/*
* The sci generates interrupts during the break,
* 1 per millisecond or so during the break period, for 9600 baud. * 1 per millisecond or so during the break period, for 9600 baud.
* So dont bother disabling interrupts. * So dont bother disabling interrupts.
* But dont want more than 1 break event. * But dont want more than 1 break event.
* Use a kernel timer to periodically poll the rx line until * Use a kernel timer to periodically poll the rx line until
* the break is finished. * the break is finished.
*/ */
static void sci_schedule_break_timer(struct sci_port *port) static inline void sci_schedule_break_timer(struct sci_port *port)
{ {
port->break_timer.expires = jiffies + SCI_BREAK_JIFFIES; mod_timer(&port->break_timer, jiffies + SCI_BREAK_JIFFIES);
add_timer(&port->break_timer);
} }
/* Ensure that two consecutive samples find the break over. */ /* Ensure that two consecutive samples find the break over. */
static void sci_break_timer(unsigned long data) static void sci_break_timer(unsigned long data)
{ {
...@@ -594,7 +573,7 @@ static void sci_break_timer(unsigned long data) ...@@ -594,7 +573,7 @@ static void sci_break_timer(unsigned long data)
port->break_flag = 0; port->break_flag = 0;
} }
static inline int sci_handle_errors(struct uart_port *port) static int sci_handle_errors(struct uart_port *port)
{ {
int copied = 0; int copied = 0;
unsigned short status = sci_in(port, SCxSR); unsigned short status = sci_in(port, SCxSR);
...@@ -650,7 +629,7 @@ static inline int sci_handle_errors(struct uart_port *port) ...@@ -650,7 +629,7 @@ static inline int sci_handle_errors(struct uart_port *port)
return copied; return copied;
} }
static inline int sci_handle_fifo_overrun(struct uart_port *port) static int sci_handle_fifo_overrun(struct uart_port *port)
{ {
struct tty_struct *tty = port->state->port.tty; struct tty_struct *tty = port->state->port.tty;
int copied = 0; int copied = 0;
...@@ -671,7 +650,7 @@ static inline int sci_handle_fifo_overrun(struct uart_port *port) ...@@ -671,7 +650,7 @@ static inline int sci_handle_fifo_overrun(struct uart_port *port)
return copied; return copied;
} }
static inline int sci_handle_breaks(struct uart_port *port) static int sci_handle_breaks(struct uart_port *port)
{ {
int copied = 0; int copied = 0;
unsigned short status = sci_in(port, SCxSR); unsigned short status = sci_in(port, SCxSR);
...@@ -794,7 +773,7 @@ static inline unsigned long port_rx_irq_mask(struct uart_port *port) ...@@ -794,7 +773,7 @@ static inline unsigned long port_rx_irq_mask(struct uart_port *port)
* it's unset, it's logically inferred that there's no point in * it's unset, it's logically inferred that there's no point in
* testing for it. * testing for it.
*/ */
return SCSCR_RIE | (to_sci_port(port)->scscr & SCSCR_REIE); return SCSCR_RIE | (to_sci_port(port)->cfg->scscr & SCSCR_REIE);
} }
static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
...@@ -839,17 +818,18 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) ...@@ -839,17 +818,18 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
static int sci_notifier(struct notifier_block *self, static int sci_notifier(struct notifier_block *self,
unsigned long phase, void *p) unsigned long phase, void *p)
{ {
struct sh_sci_priv *priv = container_of(self,
struct sh_sci_priv, clk_nb);
struct sci_port *sci_port; struct sci_port *sci_port;
unsigned long flags; unsigned long flags;
sci_port = container_of(self, struct sci_port, freq_transition);
if ((phase == CPUFREQ_POSTCHANGE) || if ((phase == CPUFREQ_POSTCHANGE) ||
(phase == CPUFREQ_RESUMECHANGE)) { (phase == CPUFREQ_RESUMECHANGE)) {
spin_lock_irqsave(&priv->lock, flags); struct uart_port *port = &sci_port->port;
list_for_each_entry(sci_port, &priv->ports, node)
sci_port->port.uartclk = clk_get_rate(sci_port->iclk); spin_lock_irqsave(&port->lock, flags);
spin_unlock_irqrestore(&priv->lock, flags); port->uartclk = clk_get_rate(sci_port->iclk);
spin_unlock_irqrestore(&port->lock, flags);
} }
return NOTIFY_OK; return NOTIFY_OK;
...@@ -882,21 +862,21 @@ static int sci_request_irq(struct sci_port *port) ...@@ -882,21 +862,21 @@ static int sci_request_irq(struct sci_port *port)
const char *desc[] = { "SCI Receive Error", "SCI Receive Data Full", const char *desc[] = { "SCI Receive Error", "SCI Receive Data Full",
"SCI Transmit Data Empty", "SCI Break" }; "SCI Transmit Data Empty", "SCI Break" };
if (port->irqs[0] == port->irqs[1]) { if (port->cfg->irqs[0] == port->cfg->irqs[1]) {
if (unlikely(!port->irqs[0])) if (unlikely(!port->cfg->irqs[0]))
return -ENODEV; return -ENODEV;
if (request_irq(port->irqs[0], sci_mpxed_interrupt, if (request_irq(port->cfg->irqs[0], sci_mpxed_interrupt,
IRQF_DISABLED, "sci", port)) { IRQF_DISABLED, "sci", port)) {
dev_err(port->port.dev, "Can't allocate IRQ\n"); dev_err(port->port.dev, "Can't allocate IRQ\n");
return -ENODEV; return -ENODEV;
} }
} else { } else {
for (i = 0; i < ARRAY_SIZE(handlers); i++) { for (i = 0; i < ARRAY_SIZE(handlers); i++) {
if (unlikely(!port->irqs[i])) if (unlikely(!port->cfg->irqs[i]))
continue; continue;
if (request_irq(port->irqs[i], handlers[i], if (request_irq(port->cfg->irqs[i], handlers[i],
IRQF_DISABLED, desc[i], port)) { IRQF_DISABLED, desc[i], port)) {
dev_err(port->port.dev, "Can't allocate IRQ\n"); dev_err(port->port.dev, "Can't allocate IRQ\n");
return -ENODEV; return -ENODEV;
...@@ -911,14 +891,14 @@ static void sci_free_irq(struct sci_port *port) ...@@ -911,14 +891,14 @@ static void sci_free_irq(struct sci_port *port)
{ {
int i; int i;
if (port->irqs[0] == port->irqs[1]) if (port->cfg->irqs[0] == port->cfg->irqs[1])
free_irq(port->irqs[0], port); free_irq(port->cfg->irqs[0], port);
else { else {
for (i = 0; i < ARRAY_SIZE(port->irqs); i++) { for (i = 0; i < ARRAY_SIZE(port->cfg->irqs); i++) {
if (!port->irqs[i]) if (!port->cfg->irqs[i])
continue; continue;
free_irq(port->irqs[i], port); free_irq(port->cfg->irqs[i], port);
} }
} }
} }
...@@ -1037,9 +1017,6 @@ static void sci_dma_rx_complete(void *arg) ...@@ -1037,9 +1017,6 @@ static void sci_dma_rx_complete(void *arg)
schedule_work(&s->work_rx); schedule_work(&s->work_rx);
} }
static void sci_start_rx(struct uart_port *port);
static void sci_start_tx(struct uart_port *port);
static void sci_rx_dma_release(struct sci_port *s, bool enable_pio) static void sci_rx_dma_release(struct sci_port *s, bool enable_pio)
{ {
struct dma_chan *chan = s->chan_rx; struct dma_chan *chan = s->chan_rx;
...@@ -1325,7 +1302,7 @@ static void rx_timer_fn(unsigned long arg) ...@@ -1325,7 +1302,7 @@ static void rx_timer_fn(unsigned long arg)
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) { if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
scr &= ~0x4000; scr &= ~0x4000;
enable_irq(s->irqs[1]); enable_irq(s->cfg->irqs[1]);
} }
sci_out(port, SCSCR, scr | SCSCR_RIE); sci_out(port, SCSCR, scr | SCSCR_RIE);
dev_dbg(port->dev, "DMA Rx timed out\n"); dev_dbg(port->dev, "DMA Rx timed out\n");
...@@ -1341,9 +1318,9 @@ static void sci_request_dma(struct uart_port *port) ...@@ -1341,9 +1318,9 @@ static void sci_request_dma(struct uart_port *port)
int nent; int nent;
dev_dbg(port->dev, "%s: port %d DMA %p\n", __func__, dev_dbg(port->dev, "%s: port %d DMA %p\n", __func__,
port->line, s->dma_dev); port->line, s->cfg->dma_dev);
if (!s->dma_dev) if (!s->cfg->dma_dev)
return; return;
dma_cap_zero(mask); dma_cap_zero(mask);
...@@ -1352,8 +1329,8 @@ static void sci_request_dma(struct uart_port *port) ...@@ -1352,8 +1329,8 @@ static void sci_request_dma(struct uart_port *port)
param = &s->param_tx; param = &s->param_tx;
/* Slave ID, e.g., SHDMA_SLAVE_SCIF0_TX */ /* Slave ID, e.g., SHDMA_SLAVE_SCIF0_TX */
param->slave_id = s->slave_tx; param->slave_id = s->cfg->dma_slave_tx;
param->dma_dev = s->dma_dev; param->dma_dev = s->cfg->dma_dev;
s->cookie_tx = -EINVAL; s->cookie_tx = -EINVAL;
chan = dma_request_channel(mask, filter, param); chan = dma_request_channel(mask, filter, param);
...@@ -1381,8 +1358,8 @@ static void sci_request_dma(struct uart_port *port) ...@@ -1381,8 +1358,8 @@ static void sci_request_dma(struct uart_port *port)
param = &s->param_rx; param = &s->param_rx;
/* Slave ID, e.g., SHDMA_SLAVE_SCIF0_RX */ /* Slave ID, e.g., SHDMA_SLAVE_SCIF0_RX */
param->slave_id = s->slave_rx; param->slave_id = s->cfg->dma_slave_rx;
param->dma_dev = s->dma_dev; param->dma_dev = s->cfg->dma_dev;
chan = dma_request_channel(mask, filter, param); chan = dma_request_channel(mask, filter, param);
dev_dbg(port->dev, "%s: RX: got channel %p\n", __func__, chan); dev_dbg(port->dev, "%s: RX: got channel %p\n", __func__, chan);
...@@ -1427,7 +1404,7 @@ static void sci_free_dma(struct uart_port *port) ...@@ -1427,7 +1404,7 @@ static void sci_free_dma(struct uart_port *port)
{ {
struct sci_port *s = to_sci_port(port); struct sci_port *s = to_sci_port(port);
if (!s->dma_dev) if (!s->cfg->dma_dev)
return; return;
if (s->chan_tx) if (s->chan_tx)
...@@ -1435,21 +1412,32 @@ static void sci_free_dma(struct uart_port *port) ...@@ -1435,21 +1412,32 @@ static void sci_free_dma(struct uart_port *port)
if (s->chan_rx) if (s->chan_rx)
sci_rx_dma_release(s, false); sci_rx_dma_release(s, false);
} }
#else
static inline void sci_request_dma(struct uart_port *port)
{
}
static inline void sci_free_dma(struct uart_port *port)
{
}
#endif #endif
static int sci_startup(struct uart_port *port) static int sci_startup(struct uart_port *port)
{ {
struct sci_port *s = to_sci_port(port); struct sci_port *s = to_sci_port(port);
int ret;
dev_dbg(port->dev, "%s(%d)\n", __func__, port->line); dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
if (s->enable) if (s->enable)
s->enable(port); s->enable(port);
sci_request_irq(s); ret = sci_request_irq(s);
#ifdef CONFIG_SERIAL_SH_SCI_DMA if (unlikely(ret < 0))
return ret;
sci_request_dma(port); sci_request_dma(port);
#endif
sci_start_tx(port); sci_start_tx(port);
sci_start_rx(port); sci_start_rx(port);
...@@ -1464,9 +1452,8 @@ static void sci_shutdown(struct uart_port *port) ...@@ -1464,9 +1452,8 @@ static void sci_shutdown(struct uart_port *port)
sci_stop_rx(port); sci_stop_rx(port);
sci_stop_tx(port); sci_stop_tx(port);
#ifdef CONFIG_SERIAL_SH_SCI_DMA
sci_free_dma(port); sci_free_dma(port);
#endif
sci_free_irq(s); sci_free_irq(s);
if (s->disable) if (s->disable)
...@@ -1491,6 +1478,7 @@ static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps, ...@@ -1491,6 +1478,7 @@ static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps,
/* Warn, but use a safe default */ /* Warn, but use a safe default */
WARN_ON(1); WARN_ON(1);
return ((freq + 16 * bps) / (32 * bps) - 1); return ((freq + 16 * bps) / (32 * bps) - 1);
} }
...@@ -1514,7 +1502,10 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, ...@@ -1514,7 +1502,10 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
baud = uart_get_baud_rate(port, termios, old, 0, max_baud); baud = uart_get_baud_rate(port, termios, old, 0, max_baud);
if (likely(baud && port->uartclk)) if (likely(baud && port->uartclk))
t = sci_scbrr_calc(s->scbrr_algo_id, baud, port->uartclk); t = sci_scbrr_calc(s->cfg->scbrr_algo_id, baud, port->uartclk);
if (s->enable)
s->enable(port);
do { do {
status = sci_in(port, SCxSR); status = sci_in(port, SCxSR);
...@@ -1526,6 +1517,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, ...@@ -1526,6 +1517,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
sci_out(port, SCFCR, scfcr | SCFCR_RFRST | SCFCR_TFRST); sci_out(port, SCFCR, scfcr | SCFCR_RFRST | SCFCR_TFRST);
smr_val = sci_in(port, SCSMR) & 3; smr_val = sci_in(port, SCSMR) & 3;
if ((termios->c_cflag & CSIZE) == CS7) if ((termios->c_cflag & CSIZE) == CS7)
smr_val |= 0x40; smr_val |= 0x40;
if (termios->c_cflag & PARENB) if (termios->c_cflag & PARENB)
...@@ -1540,7 +1532,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, ...@@ -1540,7 +1532,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
sci_out(port, SCSMR, smr_val); sci_out(port, SCSMR, smr_val);
dev_dbg(port->dev, "%s: SMR %x, t %x, SCSCR %x\n", __func__, smr_val, t, dev_dbg(port->dev, "%s: SMR %x, t %x, SCSCR %x\n", __func__, smr_val, t,
s->scscr); s->cfg->scscr);
if (t > 0) { if (t > 0) {
if (t >= 256) { if (t >= 256) {
...@@ -1556,7 +1548,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, ...@@ -1556,7 +1548,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
sci_init_pins(port, termios->c_cflag); sci_init_pins(port, termios->c_cflag);
sci_out(port, SCFCR, scfcr | ((termios->c_cflag & CRTSCTS) ? SCFCR_MCE : 0)); sci_out(port, SCFCR, scfcr | ((termios->c_cflag & CRTSCTS) ? SCFCR_MCE : 0));
sci_out(port, SCSCR, s->scscr); sci_out(port, SCSCR, s->cfg->scscr);
#ifdef CONFIG_SERIAL_SH_SCI_DMA #ifdef CONFIG_SERIAL_SH_SCI_DMA
/* /*
...@@ -1582,6 +1574,9 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, ...@@ -1582,6 +1574,9 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
if ((termios->c_cflag & CREAD) != 0) if ((termios->c_cflag & CREAD) != 0)
sci_start_rx(port); sci_start_rx(port);
if (s->disable)
s->disable(port);
} }
static const char *sci_type(struct uart_port *port) static const char *sci_type(struct uart_port *port)
...@@ -1602,31 +1597,33 @@ static const char *sci_type(struct uart_port *port) ...@@ -1602,31 +1597,33 @@ static const char *sci_type(struct uart_port *port)
return NULL; return NULL;
} }
static void sci_release_port(struct uart_port *port) static inline unsigned long sci_port_size(struct uart_port *port)
{ {
/* Nothing here yet .. */ /*
} * Pick an arbitrary size that encapsulates all of the base
* registers by default. This can be optimized later, or derived
static int sci_request_port(struct uart_port *port) * from platform resource data at such a time that ports begin to
{ * behave more erratically.
/* Nothing here yet .. */ */
return 0; return 64;
} }
static void sci_config_port(struct uart_port *port, int flags) static int sci_remap_port(struct uart_port *port)
{ {
struct sci_port *s = to_sci_port(port); unsigned long size = sci_port_size(port);
port->type = s->type;
/*
* Nothing to do if there's already an established membase.
*/
if (port->membase) if (port->membase)
return; return 0;
if (port->flags & UPF_IOREMAP) { if (port->flags & UPF_IOREMAP) {
port->membase = ioremap_nocache(port->mapbase, 0x40); port->membase = ioremap_nocache(port->mapbase, size);
if (unlikely(!port->membase)) {
if (IS_ERR(port->membase))
dev_err(port->dev, "can't remap port#%d\n", port->line); dev_err(port->dev, "can't remap port#%d\n", port->line);
return -ENXIO;
}
} else { } else {
/* /*
* For the simple (and majority of) cases where we don't * For the simple (and majority of) cases where we don't
...@@ -1635,13 +1632,54 @@ static void sci_config_port(struct uart_port *port, int flags) ...@@ -1635,13 +1632,54 @@ static void sci_config_port(struct uart_port *port, int flags)
*/ */
port->membase = (void __iomem *)port->mapbase; port->membase = (void __iomem *)port->mapbase;
} }
return 0;
}
static void sci_release_port(struct uart_port *port)
{
if (port->flags & UPF_IOREMAP) {
iounmap(port->membase);
port->membase = NULL;
}
release_mem_region(port->mapbase, sci_port_size(port));
}
static int sci_request_port(struct uart_port *port)
{
unsigned long size = sci_port_size(port);
struct resource *res;
int ret;
res = request_mem_region(port->mapbase, size, dev_name(port->dev));
if (unlikely(res == NULL))
return -EBUSY;
ret = sci_remap_port(port);
if (unlikely(ret != 0)) {
release_resource(res);
return ret;
}
return 0;
}
static void sci_config_port(struct uart_port *port, int flags)
{
if (flags & UART_CONFIG_TYPE) {
struct sci_port *sport = to_sci_port(port);
port->type = sport->cfg->type;
sci_request_port(port);
}
} }
static int sci_verify_port(struct uart_port *port, struct serial_struct *ser) static int sci_verify_port(struct uart_port *port, struct serial_struct *ser)
{ {
struct sci_port *s = to_sci_port(port); struct sci_port *s = to_sci_port(port);
if (ser->irq != s->irqs[SCIx_TXI_IRQ] || ser->irq > nr_irqs) if (ser->irq != s->cfg->irqs[SCIx_TXI_IRQ] || ser->irq > nr_irqs)
return -EINVAL; return -EINVAL;
if (ser->baud_base < 2400) if (ser->baud_base < 2400)
/* No paper tape reader for Mitch.. */ /* No paper tape reader for Mitch.. */
...@@ -1726,36 +1764,29 @@ static int __devinit sci_init_single(struct platform_device *dev, ...@@ -1726,36 +1764,29 @@ static int __devinit sci_init_single(struct platform_device *dev,
sci_port->break_timer.function = sci_break_timer; sci_port->break_timer.function = sci_break_timer;
init_timer(&sci_port->break_timer); init_timer(&sci_port->break_timer);
port->mapbase = p->mapbase; sci_port->cfg = p;
port->membase = p->membase;
port->irq = p->irqs[SCIx_TXI_IRQ]; port->mapbase = p->mapbase;
port->type = p->type;
port->flags = p->flags; port->flags = p->flags;
sci_port->type = port->type = p->type;
sci_port->scscr = p->scscr;
sci_port->scbrr_algo_id = p->scbrr_algo_id;
#ifdef CONFIG_SERIAL_SH_SCI_DMA /*
sci_port->dma_dev = p->dma_dev; * The UART port needs an IRQ value, so we peg this to the TX IRQ
sci_port->slave_tx = p->dma_slave_tx; * for the multi-IRQ ports, which is where we are primarily
sci_port->slave_rx = p->dma_slave_rx; * concerned with the shutdown path synchronization.
*
* For the muxed case there's nothing more to do.
*/
port->irq = p->irqs[SCIx_TXI_IRQ];
dev_dbg(port->dev, "%s: DMA device %p, tx %d, rx %d\n", __func__, if (p->dma_dev)
p->dma_dev, p->dma_slave_tx, p->dma_slave_rx); dev_dbg(port->dev, "DMA device %p, tx %d, rx %d\n",
#endif p->dma_dev, p->dma_slave_tx, p->dma_slave_rx);
memcpy(&sci_port->irqs, &p->irqs, sizeof(p->irqs));
return 0; return 0;
} }
#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
static struct tty_driver *serial_console_device(struct console *co, int *index)
{
struct uart_driver *p = &sci_uart_driver;
*index = co->index;
return p->tty_driver;
}
static void serial_console_putchar(struct uart_port *port, int ch) static void serial_console_putchar(struct uart_port *port, int ch)
{ {
sci_poll_put_char(port, ch); sci_poll_put_char(port, ch);
...@@ -1768,8 +1799,8 @@ static void serial_console_putchar(struct uart_port *port, int ch) ...@@ -1768,8 +1799,8 @@ static void serial_console_putchar(struct uart_port *port, int ch)
static void serial_console_write(struct console *co, const char *s, static void serial_console_write(struct console *co, const char *s,
unsigned count) unsigned count)
{ {
struct uart_port *port = co->data; struct sci_port *sci_port = &sci_ports[co->index];
struct sci_port *sci_port = to_sci_port(port); struct uart_port *port = &sci_port->port;
unsigned short bits; unsigned short bits;
if (sci_port->enable) if (sci_port->enable)
...@@ -1797,32 +1828,17 @@ static int __devinit serial_console_setup(struct console *co, char *options) ...@@ -1797,32 +1828,17 @@ static int __devinit serial_console_setup(struct console *co, char *options)
int ret; int ret;
/* /*
* Check whether an invalid uart number has been specified, and * Refuse to handle any bogus ports.
* if so, search for the first available port that does have
* console support.
*/
if (co->index >= SCI_NPORTS)
co->index = 0;
if (co->data) {
port = co->data;
sci_port = to_sci_port(port);
} else {
sci_port = &sci_ports[co->index];
port = &sci_port->port;
co->data = port;
}
/*
* Also need to check port->type, we don't actually have any
* UPIO_PORT ports, but uart_report_port() handily misreports
* it anyways if we don't have a port available by the time this is
* called.
*/ */
if (!port->type) if (co->index < 0 || co->index >= SCI_NPORTS)
return -ENODEV; return -ENODEV;
sci_config_port(port, 0); sci_port = &sci_ports[co->index];
port = &sci_port->port;
ret = sci_remap_port(port);
if (unlikely(ret != 0))
return ret;
if (sci_port->enable) if (sci_port->enable)
sci_port->enable(port); sci_port->enable(port);
...@@ -1842,11 +1858,12 @@ static int __devinit serial_console_setup(struct console *co, char *options) ...@@ -1842,11 +1858,12 @@ static int __devinit serial_console_setup(struct console *co, char *options)
static struct console serial_console = { static struct console serial_console = {
.name = "ttySC", .name = "ttySC",
.device = serial_console_device, .device = uart_console_device,
.write = serial_console_write, .write = serial_console_write,
.setup = serial_console_setup, .setup = serial_console_setup,
.flags = CON_PRINTBUFFER, .flags = CON_PRINTBUFFER,
.index = -1, .index = -1,
.data = &sci_uart_driver,
}; };
static int __init sci_console_init(void) static int __init sci_console_init(void)
...@@ -1856,14 +1873,39 @@ static int __init sci_console_init(void) ...@@ -1856,14 +1873,39 @@ static int __init sci_console_init(void)
} }
console_initcall(sci_console_init); console_initcall(sci_console_init);
static struct sci_port early_serial_port;
static struct console early_serial_console = { static struct console early_serial_console = {
.name = "early_ttySC", .name = "early_ttySC",
.write = serial_console_write, .write = serial_console_write,
.flags = CON_PRINTBUFFER, .flags = CON_PRINTBUFFER,
.index = -1,
}; };
static char early_serial_buf[32]; static char early_serial_buf[32];
static int __devinit sci_probe_earlyprintk(struct platform_device *pdev)
{
struct plat_sci_port *cfg = pdev->dev.platform_data;
if (early_serial_console.data)
return -EEXIST;
early_serial_console.index = pdev->id;
sci_init_single(NULL, &sci_ports[pdev->id], pdev->id, cfg);
serial_console_setup(&early_serial_console, early_serial_buf);
if (!strstr(early_serial_buf, "keep"))
early_serial_console.flags |= CON_BOOT;
register_console(&early_serial_console);
return 0;
}
#else
static inline int __devinit sci_probe_earlyprintk(struct platform_device *pdev)
{
return -EINVAL;
}
#endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */ #endif /* CONFIG_SERIAL_SH_SCI_CONSOLE */
#if defined(CONFIG_SERIAL_SH_SCI_CONSOLE) #if defined(CONFIG_SERIAL_SH_SCI_CONSOLE)
...@@ -1885,24 +1927,18 @@ static struct uart_driver sci_uart_driver = { ...@@ -1885,24 +1927,18 @@ static struct uart_driver sci_uart_driver = {
.cons = SCI_CONSOLE, .cons = SCI_CONSOLE,
}; };
static int sci_remove(struct platform_device *dev) static int sci_remove(struct platform_device *dev)
{ {
struct sh_sci_priv *priv = platform_get_drvdata(dev); struct sci_port *port = platform_get_drvdata(dev);
struct sci_port *p;
unsigned long flags;
cpufreq_unregister_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER); cpufreq_unregister_notifier(&port->freq_transition,
CPUFREQ_TRANSITION_NOTIFIER);
spin_lock_irqsave(&priv->lock, flags); uart_remove_one_port(&sci_uart_driver, &port->port);
list_for_each_entry(p, &priv->ports, node) {
uart_remove_one_port(&sci_uart_driver, &p->port); clk_put(port->iclk);
clk_put(p->iclk); clk_put(port->fclk);
clk_put(p->fclk);
}
spin_unlock_irqrestore(&priv->lock, flags);
kfree(priv);
return 0; return 0;
} }
...@@ -1911,8 +1947,6 @@ static int __devinit sci_probe_single(struct platform_device *dev, ...@@ -1911,8 +1947,6 @@ static int __devinit sci_probe_single(struct platform_device *dev,
struct plat_sci_port *p, struct plat_sci_port *p,
struct sci_port *sciport) struct sci_port *sciport)
{ {
struct sh_sci_priv *priv = platform_get_drvdata(dev);
unsigned long flags;
int ret; int ret;
/* Sanity check */ /* Sanity check */
...@@ -1929,68 +1963,35 @@ static int __devinit sci_probe_single(struct platform_device *dev, ...@@ -1929,68 +1963,35 @@ static int __devinit sci_probe_single(struct platform_device *dev,
if (ret) if (ret)
return ret; return ret;
ret = uart_add_one_port(&sci_uart_driver, &sciport->port); return uart_add_one_port(&sci_uart_driver, &sciport->port);
if (ret)
return ret;
INIT_LIST_HEAD(&sciport->node);
spin_lock_irqsave(&priv->lock, flags);
list_add(&sciport->node, &priv->ports);
spin_unlock_irqrestore(&priv->lock, flags);
return 0;
} }
/*
* Register a set of serial devices attached to a platform device. The
* list is terminated with a zero flags entry, which means we expect
* all entries to have at least UPF_BOOT_AUTOCONF set. Platforms that need
* remapping (such as sh64) should also set UPF_IOREMAP.
*/
static int __devinit sci_probe(struct platform_device *dev) static int __devinit sci_probe(struct platform_device *dev)
{ {
struct plat_sci_port *p = dev->dev.platform_data; struct plat_sci_port *p = dev->dev.platform_data;
struct sh_sci_priv *priv; struct sci_port *sp = &sci_ports[dev->id];
int i, ret = -EINVAL; int ret;
#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE /*
if (is_early_platform_device(dev)) { * If we've come here via earlyprintk initialization, head off to
if (dev->id == -1) * the special early probe. We don't have sufficient device state
return -ENOTSUPP; * to make it beyond this yet.
early_serial_console.index = dev->id; */
early_serial_console.data = &early_serial_port.port; if (is_early_platform_device(dev))
sci_init_single(NULL, &early_serial_port, dev->id, p); return sci_probe_earlyprintk(dev);
serial_console_setup(&early_serial_console, early_serial_buf);
if (!strstr(early_serial_buf, "keep"))
early_serial_console.flags |= CON_BOOT;
register_console(&early_serial_console);
return 0;
}
#endif
priv = kzalloc(sizeof(*priv), GFP_KERNEL); platform_set_drvdata(dev, sp);
if (!priv)
return -ENOMEM;
INIT_LIST_HEAD(&priv->ports); ret = sci_probe_single(dev, dev->id, p, sp);
spin_lock_init(&priv->lock); if (ret)
platform_set_drvdata(dev, priv); goto err_unreg;
priv->clk_nb.notifier_call = sci_notifier; sp->freq_transition.notifier_call = sci_notifier;
cpufreq_register_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER);
if (dev->id != -1) { ret = cpufreq_register_notifier(&sp->freq_transition,
ret = sci_probe_single(dev, dev->id, p, &sci_ports[dev->id]); CPUFREQ_TRANSITION_NOTIFIER);
if (ret) if (unlikely(ret < 0))
goto err_unreg; goto err_unreg;
} else {
for (i = 0; p && p->flags != 0; p++, i++) {
ret = sci_probe_single(dev, i, p, &sci_ports[i]);
if (ret)
goto err_unreg;
}
}
#ifdef CONFIG_SH_STANDARD_BIOS #ifdef CONFIG_SH_STANDARD_BIOS
sh_bios_gdb_detach(); sh_bios_gdb_detach();
...@@ -2005,28 +2006,20 @@ static int __devinit sci_probe(struct platform_device *dev) ...@@ -2005,28 +2006,20 @@ static int __devinit sci_probe(struct platform_device *dev)
static int sci_suspend(struct device *dev) static int sci_suspend(struct device *dev)
{ {
struct sh_sci_priv *priv = dev_get_drvdata(dev); struct sci_port *sport = dev_get_drvdata(dev);
struct sci_port *p;
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags); if (sport)
list_for_each_entry(p, &priv->ports, node) uart_suspend_port(&sci_uart_driver, &sport->port);
uart_suspend_port(&sci_uart_driver, &p->port);
spin_unlock_irqrestore(&priv->lock, flags);
return 0; return 0;
} }
static int sci_resume(struct device *dev) static int sci_resume(struct device *dev)
{ {
struct sh_sci_priv *priv = dev_get_drvdata(dev); struct sci_port *sport = dev_get_drvdata(dev);
struct sci_port *p;
unsigned long flags;
spin_lock_irqsave(&priv->lock, flags); if (sport)
list_for_each_entry(p, &priv->ports, node) uart_resume_port(&sci_uart_driver, &sport->port);
uart_resume_port(&sci_uart_driver, &p->port);
spin_unlock_irqrestore(&priv->lock, flags);
return 0; return 0;
} }
......
...@@ -54,9 +54,6 @@ ...@@ -54,9 +54,6 @@
# define PBCR 0xa4050102 # define PBCR 0xa4050102
#elif defined(CONFIG_CPU_SUBTYPE_SH7343) #elif defined(CONFIG_CPU_SUBTYPE_SH7343)
# define SCSPTR0 0xffe00010 /* 16 bit SCIF */ # define SCSPTR0 0xffe00010 /* 16 bit SCIF */
# define SCSPTR1 0xffe10010 /* 16 bit SCIF */
# define SCSPTR2 0xffe20010 /* 16 bit SCIF */
# define SCSPTR3 0xffe30010 /* 16 bit SCIF */
#elif defined(CONFIG_CPU_SUBTYPE_SH7722) #elif defined(CONFIG_CPU_SUBTYPE_SH7722)
# define PADR 0xA4050120 # define PADR 0xA4050120
# define PSDR 0xA405013e # define PSDR 0xA405013e
...@@ -69,77 +66,42 @@ ...@@ -69,77 +66,42 @@
# define SCIF_ORER 0x0001 /* overrun error bit */ # define SCIF_ORER 0x0001 /* overrun error bit */
#elif defined(CONFIG_CPU_SUBTYPE_SH7723) #elif defined(CONFIG_CPU_SUBTYPE_SH7723)
# define SCSPTR0 0xa4050160 # define SCSPTR0 0xa4050160
# define SCSPTR1 0xa405013e
# define SCSPTR2 0xa4050160
# define SCSPTR3 0xa405013e
# define SCSPTR4 0xa4050128
# define SCSPTR5 0xa4050128
# define SCIF_ORER 0x0001 /* overrun error bit */ # define SCIF_ORER 0x0001 /* overrun error bit */
#elif defined(CONFIG_CPU_SUBTYPE_SH7724) #elif defined(CONFIG_CPU_SUBTYPE_SH7724)
# define SCIF_ORER 0x0001 /* overrun error bit */ # define SCIF_ORER 0x0001 /* overrun error bit */
#elif defined(CONFIG_CPU_SUBTYPE_SH4_202) #elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
# define SCSPTR2 0xffe80020 /* 16 bit SCIF */ # define SCSPTR2 0xffe80020 /* 16 bit SCIF */
# define SCIF_ORER 0x0001 /* overrun error bit */ # define SCIF_ORER 0x0001 /* overrun error bit */
#elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103)
# define SCIF_PTR2_OFFS 0x0000020
# define SCSPTR2 ((port->mapbase)+SCIF_PTR2_OFFS) /* 16 bit SCIF */
#elif defined(CONFIG_H83007) || defined(CONFIG_H83068) #elif defined(CONFIG_H83007) || defined(CONFIG_H83068)
# define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port) # define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port)
#elif defined(CONFIG_H8S2678) #elif defined(CONFIG_H8S2678)
# define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port) # define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port)
#elif defined(CONFIG_CPU_SUBTYPE_SH7757) #elif defined(CONFIG_CPU_SUBTYPE_SH7757)
# define SCSPTR0 0xfe4b0020 # define SCSPTR0 0xfe4b0020
# define SCSPTR1 0xfe4b0020
# define SCSPTR2 0xfe4b0020
# define SCIF_ORER 0x0001 # define SCIF_ORER 0x0001
# define SCIF_ONLY
#elif defined(CONFIG_CPU_SUBTYPE_SH7763) #elif defined(CONFIG_CPU_SUBTYPE_SH7763)
# define SCSPTR0 0xffe00024 /* 16 bit SCIF */ # define SCSPTR0 0xffe00024 /* 16 bit SCIF */
# define SCSPTR1 0xffe08024 /* 16 bit SCIF */
# define SCSPTR2 0xffe10020 /* 16 bit SCIF/IRDA */
# define SCIF_ORER 0x0001 /* overrun error bit */ # define SCIF_ORER 0x0001 /* overrun error bit */
#elif defined(CONFIG_CPU_SUBTYPE_SH7770) #elif defined(CONFIG_CPU_SUBTYPE_SH7770)
# define SCSPTR0 0xff923020 /* 16 bit SCIF */ # define SCSPTR0 0xff923020 /* 16 bit SCIF */
# define SCSPTR1 0xff924020 /* 16 bit SCIF */
# define SCSPTR2 0xff925020 /* 16 bit SCIF */
# define SCIF_ORER 0x0001 /* overrun error bit */ # define SCIF_ORER 0x0001 /* overrun error bit */
#elif defined(CONFIG_CPU_SUBTYPE_SH7780) #elif defined(CONFIG_CPU_SUBTYPE_SH7780)
# define SCSPTR0 0xffe00024 /* 16 bit SCIF */ # define SCSPTR0 0xffe00024 /* 16 bit SCIF */
# define SCSPTR1 0xffe10024 /* 16 bit SCIF */
# define SCIF_ORER 0x0001 /* Overrun error bit */ # define SCIF_ORER 0x0001 /* Overrun error bit */
#elif defined(CONFIG_CPU_SUBTYPE_SH7785) || \ #elif defined(CONFIG_CPU_SUBTYPE_SH7785) || \
defined(CONFIG_CPU_SUBTYPE_SH7786) defined(CONFIG_CPU_SUBTYPE_SH7786)
# define SCSPTR0 0xffea0024 /* 16 bit SCIF */ # define SCSPTR0 0xffea0024 /* 16 bit SCIF */
# define SCSPTR1 0xffeb0024 /* 16 bit SCIF */
# define SCSPTR2 0xffec0024 /* 16 bit SCIF */
# define SCSPTR3 0xffed0024 /* 16 bit SCIF */
# define SCSPTR4 0xffee0024 /* 16 bit SCIF */
# define SCSPTR5 0xffef0024 /* 16 bit SCIF */
# define SCIF_ORER 0x0001 /* Overrun error bit */ # define SCIF_ORER 0x0001 /* Overrun error bit */
#elif defined(CONFIG_CPU_SUBTYPE_SH7201) || \ #elif defined(CONFIG_CPU_SUBTYPE_SH7201) || \
defined(CONFIG_CPU_SUBTYPE_SH7203) || \ defined(CONFIG_CPU_SUBTYPE_SH7203) || \
defined(CONFIG_CPU_SUBTYPE_SH7206) || \ defined(CONFIG_CPU_SUBTYPE_SH7206) || \
defined(CONFIG_CPU_SUBTYPE_SH7263) defined(CONFIG_CPU_SUBTYPE_SH7263)
# define SCSPTR0 0xfffe8020 /* 16 bit SCIF */ # define SCSPTR0 0xfffe8020 /* 16 bit SCIF */
# define SCSPTR1 0xfffe8820 /* 16 bit SCIF */
# define SCSPTR2 0xfffe9020 /* 16 bit SCIF */
# define SCSPTR3 0xfffe9820 /* 16 bit SCIF */
# if defined(CONFIG_CPU_SUBTYPE_SH7201)
# define SCSPTR4 0xfffeA020 /* 16 bit SCIF */
# define SCSPTR5 0xfffeA820 /* 16 bit SCIF */
# define SCSPTR6 0xfffeB020 /* 16 bit SCIF */
# define SCSPTR7 0xfffeB820 /* 16 bit SCIF */
# endif
#elif defined(CONFIG_CPU_SUBTYPE_SH7619) #elif defined(CONFIG_CPU_SUBTYPE_SH7619)
# define SCSPTR0 0xf8400020 /* 16 bit SCIF */ # define SCSPTR0 0xf8400020 /* 16 bit SCIF */
# define SCSPTR1 0xf8410020 /* 16 bit SCIF */
# define SCSPTR2 0xf8420020 /* 16 bit SCIF */
# define SCIF_ORER 0x0001 /* overrun error bit */ # define SCIF_ORER 0x0001 /* overrun error bit */
#elif defined(CONFIG_CPU_SUBTYPE_SHX3) #elif defined(CONFIG_CPU_SUBTYPE_SHX3)
# define SCSPTR0 0xffc30020 /* 16 bit SCIF */ # define SCSPTR0 0xffc30020 /* 16 bit SCIF */
# define SCSPTR1 0xffc40020 /* 16 bit SCIF */
# define SCSPTR2 0xffc50020 /* 16 bit SCIF */
# define SCSPTR3 0xffc60020 /* 16 bit SCIF */
# define SCIF_ORER 0x0001 /* Overrun error bit */ # define SCIF_ORER 0x0001 /* Overrun error bit */
#else #else
# error CPU subtype not defined # error CPU subtype not defined
...@@ -411,7 +373,6 @@ SCIF_FNS(SCSPTR, 0, 0, 0x24, 16) ...@@ -411,7 +373,6 @@ SCIF_FNS(SCSPTR, 0, 0, 0x24, 16)
SCIF_FNS(SCLSR, 0, 0, 0x28, 16) SCIF_FNS(SCLSR, 0, 0, 0x28, 16)
#elif defined(CONFIG_CPU_SUBTYPE_SH7763) #elif defined(CONFIG_CPU_SUBTYPE_SH7763)
SCIF_FNS(SCFDR, 0, 0, 0x1C, 16) SCIF_FNS(SCFDR, 0, 0, 0x1C, 16)
SCIF_FNS(SCSPTR2, 0, 0, 0x20, 16)
SCIF_FNS(SCTFDR, 0x0e, 16, 0x1C, 16) SCIF_FNS(SCTFDR, 0x0e, 16, 0x1C, 16)
SCIF_FNS(SCRFDR, 0x0e, 16, 0x20, 16) SCIF_FNS(SCRFDR, 0x0e, 16, 0x20, 16)
SCIF_FNS(SCSPTR, 0, 0, 0x24, 16) SCIF_FNS(SCSPTR, 0, 0, 0x24, 16)
......
...@@ -1083,14 +1083,6 @@ config SH_WDT ...@@ -1083,14 +1083,6 @@ config SH_WDT
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called shwdt. module will be called shwdt.
config SH_WDT_MMAP
bool "Allow mmap of SH WDT"
default n
depends on SH_WDT
help
If you say Y here, user applications will be able to mmap the
WDT/CPG registers.
# SPARC Architecture # SPARC Architecture
# SPARC64 Architecture # SPARC64 Architecture
......
/* /*
* drivers/char/watchdog/shwdt.c * drivers/watchdog/shwdt.c
* *
* Watchdog driver for integrated watchdog in the SuperH processors. * Watchdog driver for integrated watchdog in the SuperH processors.
* *
* Copyright (C) 2001, 2002, 2003 Paul Mundt <lethal@linux-sh.org> * Copyright (C) 2001 - 2010 Paul Mundt <lethal@linux-sh.org>
* *
* This program is free software; you can redistribute it and/or modify it * 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 * under the terms of the GNU General Public License as published by the
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/moduleparam.h> #include <linux/moduleparam.h>
#include <linux/platform_device.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/types.h> #include <linux/types.h>
#include <linux/miscdevice.h> #include <linux/miscdevice.h>
...@@ -28,11 +29,12 @@ ...@@ -28,11 +29,12 @@
#include <linux/ioport.h> #include <linux/ioport.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/slab.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/uaccess.h> #include <linux/uaccess.h>
#include <asm/watchdog.h> #include <asm/watchdog.h>
#define PFX "shwdt: " #define DRV_NAME "sh-wdt"
/* /*
* Default clock division ratio is 5.25 msecs. For an additional table of * Default clock division ratio is 5.25 msecs. For an additional table of
...@@ -62,37 +64,36 @@ ...@@ -62,37 +64,36 @@
* misses its deadline, the kernel timer will allow the WDT to overflow. * misses its deadline, the kernel timer will allow the WDT to overflow.
*/ */
static int clock_division_ratio = WTCSR_CKS_4096; static int clock_division_ratio = WTCSR_CKS_4096;
#define next_ping_period(cks) msecs_to_jiffies(cks - 4) #define next_ping_period(cks) msecs_to_jiffies(cks - 4)
static void sh_wdt_ping(unsigned long data);
static unsigned long shwdt_is_open;
static const struct watchdog_info sh_wdt_info; static const struct watchdog_info sh_wdt_info;
static char shwdt_expect_close; static struct platform_device *sh_wdt_dev;
static DEFINE_TIMER(timer, sh_wdt_ping, 0, 0);
static unsigned long next_heartbeat;
static DEFINE_SPINLOCK(shwdt_lock); static DEFINE_SPINLOCK(shwdt_lock);
#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ #define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */
static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */
static int nowayout = WATCHDOG_NOWAYOUT; static int nowayout = WATCHDOG_NOWAYOUT;
static unsigned long next_heartbeat;
/** struct sh_wdt {
* sh_wdt_start - Start the Watchdog void __iomem *base;
* struct device *dev;
* Starts the watchdog.
*/ struct timer_list timer;
static void sh_wdt_start(void)
unsigned long enabled;
char expect_close;
};
static void sh_wdt_start(struct sh_wdt *wdt)
{ {
__u8 csr;
unsigned long flags; unsigned long flags;
u8 csr;
spin_lock_irqsave(&shwdt_lock, flags); spin_lock_irqsave(&shwdt_lock, flags);
next_heartbeat = jiffies + (heartbeat * HZ); next_heartbeat = jiffies + (heartbeat * HZ);
mod_timer(&timer, next_ping_period(clock_division_ratio)); mod_timer(&wdt->timer, next_ping_period(clock_division_ratio));
csr = sh_wdt_read_csr(); csr = sh_wdt_read_csr();
csr |= WTCSR_WT | clock_division_ratio; csr |= WTCSR_WT | clock_division_ratio;
...@@ -114,15 +115,6 @@ static void sh_wdt_start(void) ...@@ -114,15 +115,6 @@ static void sh_wdt_start(void)
sh_wdt_write_csr(csr); sh_wdt_write_csr(csr);
#ifdef CONFIG_CPU_SH2 #ifdef CONFIG_CPU_SH2
/*
* Whoever came up with the RSTCSR semantics must've been smoking
* some of the good stuff, since in addition to the WTCSR/WTCNT write
* brain-damage, it's managed to fuck things up one step further..
*
* If we need to clear the WOVF bit, the upper byte has to be 0xa5..
* but if we want to touch RSTE or RSTS, the upper byte has to be
* 0x5a..
*/
csr = sh_wdt_read_rstcsr(); csr = sh_wdt_read_rstcsr();
csr &= ~RSTCSR_RSTS; csr &= ~RSTCSR_RSTS;
sh_wdt_write_rstcsr(csr); sh_wdt_write_rstcsr(csr);
...@@ -130,30 +122,23 @@ static void sh_wdt_start(void) ...@@ -130,30 +122,23 @@ static void sh_wdt_start(void)
spin_unlock_irqrestore(&shwdt_lock, flags); spin_unlock_irqrestore(&shwdt_lock, flags);
} }
/** static void sh_wdt_stop(struct sh_wdt *wdt)
* sh_wdt_stop - Stop the Watchdog
* Stops the watchdog.
*/
static void sh_wdt_stop(void)
{ {
__u8 csr;
unsigned long flags; unsigned long flags;
u8 csr;
spin_lock_irqsave(&shwdt_lock, flags); spin_lock_irqsave(&shwdt_lock, flags);
del_timer(&timer); del_timer(&wdt->timer);
csr = sh_wdt_read_csr(); csr = sh_wdt_read_csr();
csr &= ~WTCSR_TME; csr &= ~WTCSR_TME;
sh_wdt_write_csr(csr); sh_wdt_write_csr(csr);
spin_unlock_irqrestore(&shwdt_lock, flags); spin_unlock_irqrestore(&shwdt_lock, flags);
} }
/** static inline void sh_wdt_keepalive(struct sh_wdt *wdt)
* sh_wdt_keepalive - Keep the Userspace Watchdog Alive
* The Userspace watchdog got a KeepAlive: schedule the next heartbeat.
*/
static inline void sh_wdt_keepalive(void)
{ {
unsigned long flags; unsigned long flags;
...@@ -162,10 +147,6 @@ static inline void sh_wdt_keepalive(void) ...@@ -162,10 +147,6 @@ static inline void sh_wdt_keepalive(void)
spin_unlock_irqrestore(&shwdt_lock, flags); spin_unlock_irqrestore(&shwdt_lock, flags);
} }
/**
* sh_wdt_set_heartbeat - Set the Userspace Watchdog heartbeat
* Set the Userspace Watchdog heartbeat
*/
static int sh_wdt_set_heartbeat(int t) static int sh_wdt_set_heartbeat(int t)
{ {
unsigned long flags; unsigned long flags;
...@@ -179,19 +160,14 @@ static int sh_wdt_set_heartbeat(int t) ...@@ -179,19 +160,14 @@ static int sh_wdt_set_heartbeat(int t)
return 0; return 0;
} }
/**
* sh_wdt_ping - Ping the Watchdog
* @data: Unused
*
* Clears overflow bit, resets timer counter.
*/
static void sh_wdt_ping(unsigned long data) static void sh_wdt_ping(unsigned long data)
{ {
struct sh_wdt *wdt = (struct sh_wdt *)data;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&shwdt_lock, flags); spin_lock_irqsave(&shwdt_lock, flags);
if (time_before(jiffies, next_heartbeat)) { if (time_before(jiffies, next_heartbeat)) {
__u8 csr; u8 csr;
csr = sh_wdt_read_csr(); csr = sh_wdt_read_csr();
csr &= ~WTCSR_IOVF; csr &= ~WTCSR_IOVF;
...@@ -199,148 +175,76 @@ static void sh_wdt_ping(unsigned long data) ...@@ -199,148 +175,76 @@ static void sh_wdt_ping(unsigned long data)
sh_wdt_write_cnt(0); sh_wdt_write_cnt(0);
mod_timer(&timer, next_ping_period(clock_division_ratio)); mod_timer(&wdt->timer, next_ping_period(clock_division_ratio));
} else } else
printk(KERN_WARNING PFX "Heartbeat lost! Will not ping " dev_warn(wdt->dev, "Heartbeat lost! Will not ping "
"the watchdog\n"); "the watchdog\n");
spin_unlock_irqrestore(&shwdt_lock, flags); spin_unlock_irqrestore(&shwdt_lock, flags);
} }
/**
* sh_wdt_open - Open the Device
* @inode: inode of device
* @file: file handle of device
*
* Watchdog device is opened and started.
*/
static int sh_wdt_open(struct inode *inode, struct file *file) static int sh_wdt_open(struct inode *inode, struct file *file)
{ {
if (test_and_set_bit(0, &shwdt_is_open)) struct sh_wdt *wdt = platform_get_drvdata(sh_wdt_dev);
if (test_and_set_bit(0, &wdt->enabled))
return -EBUSY; return -EBUSY;
if (nowayout) if (nowayout)
__module_get(THIS_MODULE); __module_get(THIS_MODULE);
sh_wdt_start(); file->private_data = wdt;
sh_wdt_start(wdt);
return nonseekable_open(inode, file); return nonseekable_open(inode, file);
} }
/**
* sh_wdt_close - Close the Device
* @inode: inode of device
* @file: file handle of device
*
* Watchdog device is closed and stopped.
*/
static int sh_wdt_close(struct inode *inode, struct file *file) static int sh_wdt_close(struct inode *inode, struct file *file)
{ {
if (shwdt_expect_close == 42) { struct sh_wdt *wdt = file->private_data;
sh_wdt_stop();
if (wdt->expect_close == 42) {
sh_wdt_stop(wdt);
} else { } else {
printk(KERN_CRIT PFX "Unexpected close, not " dev_crit(wdt->dev, "Unexpected close, not "
"stopping watchdog!\n"); "stopping watchdog!\n");
sh_wdt_keepalive(); sh_wdt_keepalive(wdt);
} }
clear_bit(0, &shwdt_is_open); clear_bit(0, &wdt->enabled);
shwdt_expect_close = 0; wdt->expect_close = 0;
return 0; return 0;
} }
/**
* sh_wdt_write - Write to Device
* @file: file handle of device
* @buf: buffer to write
* @count: length of buffer
* @ppos: offset
*
* Pings the watchdog on write.
*/
static ssize_t sh_wdt_write(struct file *file, const char *buf, static ssize_t sh_wdt_write(struct file *file, const char *buf,
size_t count, loff_t *ppos) size_t count, loff_t *ppos)
{ {
struct sh_wdt *wdt = file->private_data;
if (count) { if (count) {
if (!nowayout) { if (!nowayout) {
size_t i; size_t i;
shwdt_expect_close = 0; wdt->expect_close = 0;
for (i = 0; i != count; i++) { for (i = 0; i != count; i++) {
char c; char c;
if (get_user(c, buf + i)) if (get_user(c, buf + i))
return -EFAULT; return -EFAULT;
if (c == 'V') if (c == 'V')
shwdt_expect_close = 42; wdt->expect_close = 42;
} }
} }
sh_wdt_keepalive(); sh_wdt_keepalive(wdt);
} }
return count; return count;
} }
/**
* sh_wdt_mmap - map WDT/CPG registers into userspace
* @file: file structure for the device
* @vma: VMA to map the registers into
*
* A simple mmap() implementation for the corner cases where the counter
* needs to be mapped in userspace directly. Due to the relatively small
* size of the area, neighbouring registers not necessarily tied to the
* CPG will also be accessible through the register page, so this remains
* configurable for users that really know what they're doing.
*
* Additionaly, the register page maps in the CPG register base relative
* to the nearest page-aligned boundary, which requires that userspace do
* the appropriate CPU subtype math for calculating the page offset for
* the counter value.
*/
static int sh_wdt_mmap(struct file *file, struct vm_area_struct *vma)
{
int ret = -ENOSYS;
#ifdef CONFIG_SH_WDT_MMAP
unsigned long addr;
/* Only support the simple cases where we map in a register page. */
if (((vma->vm_end - vma->vm_start) != PAGE_SIZE) || vma->vm_pgoff)
return -EINVAL;
/*
* Pick WTCNT as the start, it's usually the first register after the
* FRQCR, and neither one are generally page-aligned out of the box.
*/
addr = WTCNT & ~(PAGE_SIZE - 1);
vma->vm_flags |= VM_IO;
vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
if (io_remap_pfn_range(vma, vma->vm_start, addr >> PAGE_SHIFT,
PAGE_SIZE, vma->vm_page_prot)) {
printk(KERN_ERR PFX "%s: io_remap_pfn_range failed\n",
__func__);
return -EAGAIN;
}
ret = 0;
#endif
return ret;
}
/**
* sh_wdt_ioctl - Query Device
* @file: file handle of device
* @cmd: watchdog command
* @arg: argument
*
* Query basic information from the device or ping it, as outlined by the
* watchdog API.
*/
static long sh_wdt_ioctl(struct file *file, unsigned int cmd, static long sh_wdt_ioctl(struct file *file, unsigned int cmd,
unsigned long arg) unsigned long arg)
{ {
struct sh_wdt *wdt = file->private_data;
int new_heartbeat; int new_heartbeat;
int options, retval = -EINVAL; int options, retval = -EINVAL;
...@@ -356,18 +260,18 @@ static long sh_wdt_ioctl(struct file *file, unsigned int cmd, ...@@ -356,18 +260,18 @@ static long sh_wdt_ioctl(struct file *file, unsigned int cmd,
return -EFAULT; return -EFAULT;
if (options & WDIOS_DISABLECARD) { if (options & WDIOS_DISABLECARD) {
sh_wdt_stop(); sh_wdt_stop(wdt);
retval = 0; retval = 0;
} }
if (options & WDIOS_ENABLECARD) { if (options & WDIOS_ENABLECARD) {
sh_wdt_start(); sh_wdt_start(wdt);
retval = 0; retval = 0;
} }
return retval; return retval;
case WDIOC_KEEPALIVE: case WDIOC_KEEPALIVE:
sh_wdt_keepalive(); sh_wdt_keepalive(wdt);
return 0; return 0;
case WDIOC_SETTIMEOUT: case WDIOC_SETTIMEOUT:
if (get_user(new_heartbeat, (int *)arg)) if (get_user(new_heartbeat, (int *)arg))
...@@ -376,7 +280,7 @@ static long sh_wdt_ioctl(struct file *file, unsigned int cmd, ...@@ -376,7 +280,7 @@ static long sh_wdt_ioctl(struct file *file, unsigned int cmd,
if (sh_wdt_set_heartbeat(new_heartbeat)) if (sh_wdt_set_heartbeat(new_heartbeat))
return -EINVAL; return -EINVAL;
sh_wdt_keepalive(); sh_wdt_keepalive(wdt);
/* Fall */ /* Fall */
case WDIOC_GETTIMEOUT: case WDIOC_GETTIMEOUT:
return put_user(heartbeat, (int *)arg); return put_user(heartbeat, (int *)arg);
...@@ -386,20 +290,13 @@ static long sh_wdt_ioctl(struct file *file, unsigned int cmd, ...@@ -386,20 +290,13 @@ static long sh_wdt_ioctl(struct file *file, unsigned int cmd,
return 0; return 0;
} }
/**
* sh_wdt_notify_sys - Notifier Handler
* @this: notifier block
* @code: notifier event
* @unused: unused
*
* Handles specific events, such as turning off the watchdog during a
* shutdown event.
*/
static int sh_wdt_notify_sys(struct notifier_block *this, static int sh_wdt_notify_sys(struct notifier_block *this,
unsigned long code, void *unused) unsigned long code, void *unused)
{ {
struct sh_wdt *wdt = platform_get_drvdata(sh_wdt_dev);
if (code == SYS_DOWN || code == SYS_HALT) if (code == SYS_DOWN || code == SYS_HALT)
sh_wdt_stop(); sh_wdt_stop(wdt);
return NOTIFY_DONE; return NOTIFY_DONE;
} }
...@@ -411,7 +308,6 @@ static const struct file_operations sh_wdt_fops = { ...@@ -411,7 +308,6 @@ static const struct file_operations sh_wdt_fops = {
.unlocked_ioctl = sh_wdt_ioctl, .unlocked_ioctl = sh_wdt_ioctl,
.open = sh_wdt_open, .open = sh_wdt_open,
.release = sh_wdt_close, .release = sh_wdt_close,
.mmap = sh_wdt_mmap,
}; };
static const struct watchdog_info sh_wdt_info = { static const struct watchdog_info sh_wdt_info = {
...@@ -431,66 +327,148 @@ static struct miscdevice sh_wdt_miscdev = { ...@@ -431,66 +327,148 @@ static struct miscdevice sh_wdt_miscdev = {
.fops = &sh_wdt_fops, .fops = &sh_wdt_fops,
}; };
/** static int __devinit sh_wdt_probe(struct platform_device *pdev)
* sh_wdt_init - Initialize module
* Registers the device and notifier handler. Actual device
* initialization is handled by sh_wdt_open().
*/
static int __init sh_wdt_init(void)
{ {
struct sh_wdt *wdt;
struct resource *res;
int rc; int rc;
if (clock_division_ratio < 0x5 || clock_division_ratio > 0x7) { /*
clock_division_ratio = WTCSR_CKS_4096; * As this driver only covers the global watchdog case, reject
printk(KERN_INFO PFX * any attempts to register per-CPU watchdogs.
"clock_division_ratio value must be 0x5<=x<=0x7, using %d\n", */
clock_division_ratio); if (pdev->id != -1)
return -EINVAL;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (unlikely(!res))
return -EINVAL;
if (!devm_request_mem_region(&pdev->dev, res->start,
resource_size(res), DRV_NAME))
return -EBUSY;
wdt = devm_kzalloc(&pdev->dev, sizeof(struct sh_wdt), GFP_KERNEL);
if (unlikely(!wdt)) {
rc = -ENOMEM;
goto out_release;
} }
rc = sh_wdt_set_heartbeat(heartbeat); wdt->dev = &pdev->dev;
if (unlikely(rc)) {
heartbeat = WATCHDOG_HEARTBEAT; wdt->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
printk(KERN_INFO PFX if (unlikely(!wdt->base)) {
"heartbeat value must be 1<=x<=3600, using %d\n", rc = -ENXIO;
heartbeat); goto out_err;
} }
rc = register_reboot_notifier(&sh_wdt_notifier); rc = register_reboot_notifier(&sh_wdt_notifier);
if (unlikely(rc)) { if (unlikely(rc)) {
printk(KERN_ERR PFX dev_err(&pdev->dev,
"Can't register reboot notifier (err=%d)\n", rc); "Can't register reboot notifier (err=%d)\n", rc);
return rc; goto out_unmap;
} }
sh_wdt_miscdev.parent = wdt->dev;
rc = misc_register(&sh_wdt_miscdev); rc = misc_register(&sh_wdt_miscdev);
if (unlikely(rc)) { if (unlikely(rc)) {
printk(KERN_ERR PFX dev_err(&pdev->dev,
"Can't register miscdev on minor=%d (err=%d)\n", "Can't register miscdev on minor=%d (err=%d)\n",
sh_wdt_miscdev.minor, rc); sh_wdt_miscdev.minor, rc);
unregister_reboot_notifier(&sh_wdt_notifier); goto out_unreg;
return rc;
} }
printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n", init_timer(&wdt->timer);
heartbeat, nowayout); wdt->timer.function = sh_wdt_ping;
wdt->timer.data = (unsigned long)wdt;
wdt->timer.expires = next_ping_period(clock_division_ratio);
platform_set_drvdata(pdev, wdt);
sh_wdt_dev = pdev;
dev_info(&pdev->dev, "initialized.\n");
return 0; return 0;
out_unreg:
unregister_reboot_notifier(&sh_wdt_notifier);
out_unmap:
devm_iounmap(&pdev->dev, wdt->base);
out_err:
devm_kfree(&pdev->dev, wdt);
out_release:
devm_release_mem_region(&pdev->dev, res->start, resource_size(res));
return rc;
} }
/** static int __devexit sh_wdt_remove(struct platform_device *pdev)
* sh_wdt_exit - Deinitialize module
* Unregisters the device and notifier handler. Actual device
* deinitialization is handled by sh_wdt_close().
*/
static void __exit sh_wdt_exit(void)
{ {
struct sh_wdt *wdt = platform_get_drvdata(pdev);
struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
platform_set_drvdata(pdev, NULL);
misc_deregister(&sh_wdt_miscdev); misc_deregister(&sh_wdt_miscdev);
sh_wdt_dev = NULL;
unregister_reboot_notifier(&sh_wdt_notifier); unregister_reboot_notifier(&sh_wdt_notifier);
devm_release_mem_region(&pdev->dev, res->start, resource_size(res));
devm_iounmap(&pdev->dev, wdt->base);
devm_kfree(&pdev->dev, wdt);
return 0;
} }
static struct platform_driver sh_wdt_driver = {
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
},
.probe = sh_wdt_probe,
.remove = __devexit_p(sh_wdt_remove),
};
static int __init sh_wdt_init(void)
{
int rc;
if (unlikely(clock_division_ratio < 0x5 ||
clock_division_ratio > 0x7)) {
clock_division_ratio = WTCSR_CKS_4096;
pr_info("%s: divisor must be 0x5<=x<=0x7, using %d\n",
DRV_NAME, clock_division_ratio);
}
rc = sh_wdt_set_heartbeat(heartbeat);
if (unlikely(rc)) {
heartbeat = WATCHDOG_HEARTBEAT;
pr_info("%s: heartbeat value must be 1<=x<=3600, using %d\n",
DRV_NAME, heartbeat);
}
pr_info("%s: configured with heartbeat=%d sec (nowayout=%d)\n",
DRV_NAME, heartbeat, nowayout);
return platform_driver_register(&sh_wdt_driver);
}
static void __exit sh_wdt_exit(void)
{
platform_driver_unregister(&sh_wdt_driver);
}
module_init(sh_wdt_init);
module_exit(sh_wdt_exit);
MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>"); MODULE_AUTHOR("Paul Mundt <lethal@linux-sh.org>");
MODULE_DESCRIPTION("SuperH watchdog driver"); MODULE_DESCRIPTION("SuperH watchdog driver");
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
module_param(clock_division_ratio, int, 0); module_param(clock_division_ratio, int, 0);
...@@ -507,6 +485,3 @@ module_param(nowayout, int, 0); ...@@ -507,6 +485,3 @@ module_param(nowayout, int, 0);
MODULE_PARM_DESC(nowayout, MODULE_PARM_DESC(nowayout,
"Watchdog cannot be stopped once started (default=" "Watchdog cannot be stopped once started (default="
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
module_init(sh_wdt_init);
module_exit(sh_wdt_exit);
...@@ -34,28 +34,32 @@ enum { ...@@ -34,28 +34,32 @@ enum {
SCIx_NR_IRQS, SCIx_NR_IRQS,
}; };
#define SCIx_IRQ_MUXED(irq) \
{ \
[SCIx_ERI_IRQ] = (irq), \
[SCIx_RXI_IRQ] = (irq), \
[SCIx_TXI_IRQ] = (irq), \
[SCIx_BRI_IRQ] = (irq), \
}
struct device; struct device;
/* /*
* Platform device specific platform_data struct * Platform device specific platform_data struct
*/ */
struct plat_sci_port { struct plat_sci_port {
void __iomem *membase; /* io cookie */
unsigned long mapbase; /* resource base */ unsigned long mapbase; /* resource base */
unsigned int irqs[SCIx_NR_IRQS]; /* ERI, RXI, TXI, BRI */ unsigned int irqs[SCIx_NR_IRQS]; /* ERI, RXI, TXI, BRI */
unsigned int type; /* SCI / SCIF / IRDA */ unsigned int type; /* SCI / SCIF / IRDA */
upf_t flags; /* UPF_* flags */ upf_t flags; /* UPF_* flags */
char *clk; /* clock string */
unsigned int scbrr_algo_id; /* SCBRR calculation algo */ unsigned int scbrr_algo_id; /* SCBRR calculation algo */
unsigned int scscr; /* SCSCR initialization */ unsigned int scscr; /* SCSCR initialization */
struct device *dma_dev; struct device *dma_dev;
#ifdef CONFIG_SERIAL_SH_SCI_DMA unsigned int dma_slave_tx;
unsigned int dma_slave_tx; unsigned int dma_slave_rx;
unsigned int dma_slave_rx;
#endif
}; };
#endif /* __LINUX_SERIAL_SCI_H */ #endif /* __LINUX_SERIAL_SCI_H */
...@@ -34,7 +34,7 @@ config GCOV_KERNEL ...@@ -34,7 +34,7 @@ config GCOV_KERNEL
config GCOV_PROFILE_ALL config GCOV_PROFILE_ALL
bool "Profile entire Kernel" bool "Profile entire Kernel"
depends on GCOV_KERNEL depends on GCOV_KERNEL
depends on S390 || X86 || (PPC && EXPERIMENTAL) || MICROBLAZE depends on SUPERH || S390 || X86 || (PPC && EXPERIMENTAL) || MICROBLAZE
default n default n
---help--- ---help---
This options activates profiling for the entire kernel. This options activates profiling for the entire kernel.
......
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