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. ...
This commit is contained in:
commit
241eb95600
25 changed files with 1258 additions and 560 deletions
|
@ -25,6 +25,7 @@ config SUPERH
|
|||
select GENERIC_ATOMIC64
|
||||
# Support the deprecated APIs until MFD and GPIOLIB catch up.
|
||||
select GENERIC_HARDIRQS_NO_DEPRECATED if !MFD_SUPPORT && !GPIOLIB
|
||||
select GENERIC_IRQ_SHOW
|
||||
help
|
||||
The SuperH is a RISC processor targeted for use in embedded systems
|
||||
and consumer electronics; it was also used in the Sega Dreamcast
|
||||
|
@ -434,6 +435,8 @@ config CPU_SUBTYPE_SH7757
|
|||
select CPU_SH4A
|
||||
select CPU_SHX2
|
||||
select ARCH_WANT_OPTIONAL_GPIOLIB
|
||||
select USB_ARCH_HAS_OHCI
|
||||
select USB_ARCH_HAS_EHCI
|
||||
help
|
||||
Select SH7757 if you have a SH4A SH7757 CPU.
|
||||
|
||||
|
|
|
@ -66,6 +66,11 @@ static struct resource sh_eth_resources[] = {
|
|||
.end = 0xFEE00F7C - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
}, {
|
||||
.start = 0xFEE01800, /* TSU */
|
||||
.end = 0xFEE01FFF,
|
||||
.flags = IORESOURCE_MEM,
|
||||
}, {
|
||||
|
||||
.start = 57, /* irq number */
|
||||
.flags = IORESOURCE_IRQ,
|
||||
},
|
||||
|
@ -74,6 +79,8 @@ static struct resource sh_eth_resources[] = {
|
|||
static struct sh_eth_plat_data sh7763_eth_pdata = {
|
||||
.phy = 0,
|
||||
.edmac_endian = EDMAC_LITTLE_ENDIAN,
|
||||
.register_type = SH_ETH_REG_GIGABIT,
|
||||
.phy_interface = PHY_INTERFACE_MODE_MII,
|
||||
};
|
||||
|
||||
static struct platform_device espt_eth_device = {
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/flash.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 <asm/sh_eth.h>
|
||||
#include <asm/heartbeat.h>
|
||||
|
@ -44,6 +47,17 @@ static struct platform_device heartbeat_device = {
|
|||
};
|
||||
|
||||
/* 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[] = {
|
||||
{
|
||||
.start = 0xfef00000,
|
||||
|
@ -59,6 +73,8 @@ static struct resource sh_eth0_resources[] = {
|
|||
static struct sh_eth_plat_data sh7757_eth0_pdata = {
|
||||
.phy = 1,
|
||||
.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 = {
|
||||
|
@ -86,6 +102,8 @@ static struct resource sh_eth1_resources[] = {
|
|||
static struct sh_eth_plat_data sh7757_eth1_pdata = {
|
||||
.phy = 1,
|
||||
.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 = {
|
||||
|
@ -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 = {
|
||||
&heartbeat_device,
|
||||
&sh7757_eth0_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)
|
||||
|
@ -332,6 +513,10 @@ static int __init sh7757lcr_devices_setup(void)
|
|||
gpio_request(GPIO_PTT5, NULL); /* eMMC_PRST# */
|
||||
gpio_direction_output(GPIO_PTT5, 1);
|
||||
|
||||
/* register SPI device information */
|
||||
spi_register_board_info(spi_board_info,
|
||||
ARRAY_SIZE(spi_board_info));
|
||||
|
||||
/* General platform */
|
||||
return platform_add_devices(sh7757lcr_devices,
|
||||
ARRAY_SIZE(sh7757lcr_devices));
|
||||
|
|
|
@ -142,6 +142,8 @@ static struct resource sh_eth_resources[] = {
|
|||
static struct sh_eth_plat_data sh_eth_plat = {
|
||||
.phy = 0x1f, /* SMSC LAN8700 */
|
||||
.edmac_endian = EDMAC_LITTLE_ENDIAN,
|
||||
.register_type = SH_ETH_REG_FAST_SH4,
|
||||
.phy_interface = PHY_INTERFACE_MODE_MII,
|
||||
.ether_link_active_low = 1
|
||||
};
|
||||
|
||||
|
|
|
@ -74,6 +74,10 @@ static struct resource sh_eth_resources[] = {
|
|||
.start = 0xFEE00800, /* use eth1 */
|
||||
.end = 0xFEE00F7C - 1,
|
||||
.flags = IORESOURCE_MEM,
|
||||
}, {
|
||||
.start = 0xFEE01800, /* TSU */
|
||||
.end = 0xFEE01FFF,
|
||||
.flags = IORESOURCE_MEM,
|
||||
}, {
|
||||
.start = 57, /* irq number */
|
||||
.flags = IORESOURCE_IRQ,
|
||||
|
@ -83,6 +87,8 @@ static struct resource sh_eth_resources[] = {
|
|||
static struct sh_eth_plat_data sh7763_eth_pdata = {
|
||||
.phy = 1,
|
||||
.edmac_endian = EDMAC_LITTLE_ENDIAN,
|
||||
.register_type = SH_ETH_REG_GIGABIT,
|
||||
.phy_interface = PHY_INTERFACE_MODE_MII,
|
||||
};
|
||||
|
||||
static struct platform_device sh7763rdp_eth_device = {
|
||||
|
|
|
@ -11,6 +11,8 @@ targets := vmlinux vmlinux.bin vmlinux.bin.gz \
|
|||
|
||||
OBJECTS = $(obj)/head_$(BITS).o $(obj)/misc.o $(obj)/cache.o
|
||||
|
||||
GCOV_PROFILE := n
|
||||
|
||||
#
|
||||
# IMAGE_OFFSET is the load offset of the compression loader
|
||||
#
|
||||
|
|
|
@ -38,7 +38,15 @@ CONFIG_IPV6=y
|
|||
# CONFIG_WIRELESS is not set
|
||||
CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
|
||||
# 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_SCSI=y
|
||||
CONFIG_BLK_DEV_SD=y
|
||||
CONFIG_NETDEVICES=y
|
||||
CONFIG_VITESSE_PHY=y
|
||||
CONFIG_NET_ETHERNET=y
|
||||
|
@ -53,8 +61,17 @@ CONFIG_SERIAL_SH_SCI_NR_UARTS=3
|
|||
CONFIG_SERIAL_SH_SCI_CONSOLE=y
|
||||
# CONFIG_LEGACY_PTYS is not set
|
||||
# CONFIG_HW_RANDOM is not set
|
||||
CONFIG_SPI=y
|
||||
CONFIG_SPI_SH=y
|
||||
# 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_EXT3_FS=y
|
||||
CONFIG_ISO9660_FS=y
|
||||
|
|
|
@ -1,16 +1,19 @@
|
|||
/*
|
||||
* 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
|
||||
* License. See the file "COPYING" in the main directory of this archive
|
||||
* for more details.
|
||||
*/
|
||||
#define pr_fmt(fmt) "PCI: " fmt
|
||||
|
||||
#include <linux/pci.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/async.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/clk.h>
|
||||
|
@ -31,7 +34,7 @@ static unsigned int nr_ports;
|
|||
|
||||
static struct sh7786_pcie_hwops {
|
||||
int (*core_init)(void);
|
||||
int (*port_init_hw)(struct sh7786_pcie_port *port);
|
||||
async_func_ptr *port_init_hw;
|
||||
} *sh7786_pcie_hwops;
|
||||
|
||||
static struct resource sh7786_pci0_resources[] = {
|
||||
|
@ -474,8 +477,9 @@ static int __init sh7786_pcie_core_init(void)
|
|||
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;
|
||||
|
||||
/*
|
||||
|
@ -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.
|
||||
*/
|
||||
ret = pcie_clk_init(port);
|
||||
if (unlikely(ret < 0))
|
||||
return ret;
|
||||
if (unlikely(ret < 0)) {
|
||||
pr_err("clock initialization failed for port#%d\n",
|
||||
port->index);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = phy_init(port);
|
||||
if (unlikely(ret < 0))
|
||||
return ret;
|
||||
if (unlikely(ret < 0)) {
|
||||
pr_err("phy initialization failed for port#%d\n",
|
||||
port->index);
|
||||
return;
|
||||
}
|
||||
|
||||
ret = pcie_init(port);
|
||||
if (unlikely(ret < 0))
|
||||
return ret;
|
||||
if (unlikely(ret < 0)) {
|
||||
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 = {
|
||||
|
@ -510,7 +526,7 @@ static struct sh7786_pcie_hwops sh7786_65nm_pcie_hwops __initdata = {
|
|||
static int __init sh7786_pcie_init(void)
|
||||
{
|
||||
struct clk *platclk;
|
||||
int ret = 0, i;
|
||||
int i;
|
||||
|
||||
printk(KERN_NOTICE "PCI: Starting initialization.\n");
|
||||
|
||||
|
@ -552,14 +568,10 @@ static int __init sh7786_pcie_init(void)
|
|||
port->hose = sh7786_pci_channels + i;
|
||||
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)) {
|
||||
clk_disable(platclk);
|
||||
clk_put(platclk);
|
||||
return ret;
|
||||
}
|
||||
async_synchronize_full();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -369,8 +369,11 @@
|
|||
#define __NR_recvmsg 356
|
||||
#define __NR_recvmmsg 357
|
||||
#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__
|
||||
|
||||
|
|
|
@ -390,10 +390,13 @@
|
|||
#define __NR_fanotify_init 367
|
||||
#define __NR_fanotify_mark 368
|
||||
#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__
|
||||
|
||||
#define NR_syscalls 370
|
||||
#define NR_syscalls 373
|
||||
|
||||
#define __ARCH_WANT_IPC_PARSE_VERSION
|
||||
#define __ARCH_WANT_OLD_READDIR
|
||||
|
|
|
@ -40,6 +40,11 @@
|
|||
#define CHCR_TS_LOW_SHIFT 3
|
||||
#define CHCR_TS_HIGH_MASK 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)
|
||||
#define CHCR_TS_LOW_MASK 0x00000018
|
||||
#define CHCR_TS_LOW_SHIFT 3
|
||||
|
|
|
@ -251,4 +251,36 @@ enum {
|
|||
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__ */
|
||||
|
|
|
@ -77,9 +77,10 @@ struct clk div4_clks[DIV4_NR] = {
|
|||
|
||||
#define MSTPCR0 0xffc80030
|
||||
#define MSTPCR1 0xffc80034
|
||||
#define MSTPCR2 0xffc10028
|
||||
|
||||
enum { MSTP004, MSTP000, MSTP114, MSTP113, MSTP112,
|
||||
MSTP111, MSTP110, MSTP103, MSTP102,
|
||||
MSTP111, MSTP110, MSTP103, MSTP102, MSTP220,
|
||||
MSTP_NR };
|
||||
|
||||
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),
|
||||
[MSTP103] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 3, 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 }
|
||||
|
@ -140,6 +144,7 @@ static struct clk_lookup lookups[] = {
|
|||
.clk = &mstp_clks[MSTP110],
|
||||
},
|
||||
CLKDEV_CON_ID("usb0", &mstp_clks[MSTP102]),
|
||||
CLKDEV_CON_ID("mmc0", &mstp_clks[MSTP220]),
|
||||
};
|
||||
|
||||
int __init arch_clk_init(void)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* 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
|
||||
*
|
||||
|
@ -16,6 +16,10 @@
|
|||
#include <linux/io.h>
|
||||
#include <linux/mm.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 = {
|
||||
.mapbase = 0xfe4b0000, /* SCIF2 */
|
||||
|
@ -124,12 +128,548 @@ static struct platform_device tmu1_device = {
|
|||
.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 = {
|
||||
&scif2_device,
|
||||
&scif3_device,
|
||||
&scif4_device,
|
||||
&tmu0_device,
|
||||
&tmu1_device,
|
||||
&dma0_device,
|
||||
&dma1_device,
|
||||
&dma2_device,
|
||||
&dma3_device,
|
||||
&spi0_device,
|
||||
};
|
||||
|
||||
static int __init sh7757_devices_setup(void)
|
||||
|
|
|
@ -75,7 +75,7 @@ void sh_mobile_setup_cpuidle(void)
|
|||
i = CPUIDLE_DRIVER_STATE_START;
|
||||
|
||||
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);
|
||||
state->exit_latency = 1;
|
||||
state->target_residency = 1 * 2;
|
||||
|
@ -88,7 +88,7 @@ void sh_mobile_setup_cpuidle(void)
|
|||
|
||||
if (sh_mobile_sleep_supported & SUSP_SH_SF) {
|
||||
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]",
|
||||
CPUIDLE_DESC_LEN);
|
||||
state->exit_latency = 100;
|
||||
|
@ -101,7 +101,7 @@ void sh_mobile_setup_cpuidle(void)
|
|||
|
||||
if (sh_mobile_sleep_supported & SUSP_SH_STANDBY) {
|
||||
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]",
|
||||
CPUIDLE_DESC_LEN);
|
||||
state->exit_latency = 2300;
|
||||
|
|
|
@ -34,9 +34,9 @@ void ack_bad_irq(unsigned int irq)
|
|||
|
||||
#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;
|
||||
|
||||
|
@ -49,63 +49,6 @@ static int show_other_interrupts(struct seq_file *p, int prec)
|
|||
|
||||
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
|
||||
|
||||
#ifdef CONFIG_IRQSTACKS
|
||||
|
|
|
@ -376,3 +376,6 @@ ENTRY(sys_call_table)
|
|||
.long sys_recvmsg
|
||||
.long sys_recvmmsg
|
||||
.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:
|
|||
.long sys_fanotify_init
|
||||
.long sys_fanotify_mark
|
||||
.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
|
|||
obj-$(CONFIG_UNCACHED_MAPPING) += uncached.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
|
||||
# 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
|
||||
|
|
|
@ -47,7 +47,6 @@
|
|||
#include <linux/clk.h>
|
||||
#include <linux/ctype.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/slab.h>
|
||||
|
@ -65,11 +64,8 @@
|
|||
struct sci_port {
|
||||
struct uart_port port;
|
||||
|
||||
/* Port type */
|
||||
unsigned int type;
|
||||
|
||||
/* Port IRQs: ERI, RXI, TXI, BRI (optional) */
|
||||
unsigned int irqs[SCIx_NR_IRQS];
|
||||
/* Platform configuration */
|
||||
struct plat_sci_port *cfg;
|
||||
|
||||
/* Port enable callback */
|
||||
void (*enable)(struct uart_port *port);
|
||||
|
@ -81,26 +77,15 @@ struct sci_port {
|
|||
struct timer_list break_timer;
|
||||
int break_flag;
|
||||
|
||||
/* SCSCR initialization */
|
||||
unsigned int scscr;
|
||||
|
||||
/* SCBRR calculation algo */
|
||||
unsigned int scbrr_algo_id;
|
||||
|
||||
/* Interface clock */
|
||||
struct clk *iclk;
|
||||
/* Function clock */
|
||||
struct clk *fclk;
|
||||
|
||||
struct list_head node;
|
||||
|
||||
struct dma_chan *chan_tx;
|
||||
struct dma_chan *chan_rx;
|
||||
|
||||
#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_rx[2];
|
||||
dma_cookie_t cookie_tx;
|
||||
|
@ -117,16 +102,14 @@ struct sci_port {
|
|||
struct timer_list rx_timer;
|
||||
unsigned int rx_timeout;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct sh_sci_priv {
|
||||
spinlock_t lock;
|
||||
struct list_head ports;
|
||||
struct notifier_block clk_nb;
|
||||
struct notifier_block freq_transition;
|
||||
};
|
||||
|
||||
/* Function prototypes */
|
||||
static void sci_start_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
|
||||
|
||||
|
@ -142,12 +125,6 @@ to_sci_port(struct uart_port *uart)
|
|||
#if defined(CONFIG_CONSOLE_POLL) || defined(CONFIG_SERIAL_SH_SCI_CONSOLE)
|
||||
|
||||
#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)
|
||||
{
|
||||
unsigned short status;
|
||||
|
@ -156,7 +133,7 @@ static int sci_poll_get_char(struct uart_port *port)
|
|||
do {
|
||||
status = sci_in(port, SCxSR);
|
||||
if (status & SCxSR_ERRORS(port)) {
|
||||
handle_error(port);
|
||||
sci_out(port, SCxSR, SCxSR_ERROR_CLEAR(port));
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
@ -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 */
|
||||
#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 tty_struct *tty = port->state->port.tty;
|
||||
|
@ -566,18 +543,20 @@ static inline void sci_receive_chars(struct uart_port *port)
|
|||
}
|
||||
|
||||
#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.
|
||||
* So dont bother disabling interrupts.
|
||||
* But dont want more than 1 break event.
|
||||
* Use a kernel timer to periodically poll the rx line until
|
||||
* 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;
|
||||
add_timer(&port->break_timer);
|
||||
mod_timer(&port->break_timer, jiffies + SCI_BREAK_JIFFIES);
|
||||
}
|
||||
|
||||
/* Ensure that two consecutive samples find the break over. */
|
||||
static void sci_break_timer(unsigned long data)
|
||||
{
|
||||
|
@ -594,7 +573,7 @@ static void sci_break_timer(unsigned long data)
|
|||
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;
|
||||
unsigned short status = sci_in(port, SCxSR);
|
||||
|
@ -650,7 +629,7 @@ static inline int sci_handle_errors(struct uart_port *port)
|
|||
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;
|
||||
int copied = 0;
|
||||
|
@ -671,7 +650,7 @@ static inline int sci_handle_fifo_overrun(struct uart_port *port)
|
|||
return copied;
|
||||
}
|
||||
|
||||
static inline int sci_handle_breaks(struct uart_port *port)
|
||||
static int sci_handle_breaks(struct uart_port *port)
|
||||
{
|
||||
int copied = 0;
|
||||
unsigned short status = sci_in(port, SCxSR);
|
||||
|
@ -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
|
||||
* 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)
|
||||
|
@ -839,17 +818,18 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr)
|
|||
static int sci_notifier(struct notifier_block *self,
|
||||
unsigned long phase, void *p)
|
||||
{
|
||||
struct sh_sci_priv *priv = container_of(self,
|
||||
struct sh_sci_priv, clk_nb);
|
||||
struct sci_port *sci_port;
|
||||
unsigned long flags;
|
||||
|
||||
sci_port = container_of(self, struct sci_port, freq_transition);
|
||||
|
||||
if ((phase == CPUFREQ_POSTCHANGE) ||
|
||||
(phase == CPUFREQ_RESUMECHANGE)) {
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
list_for_each_entry(sci_port, &priv->ports, node)
|
||||
sci_port->port.uartclk = clk_get_rate(sci_port->iclk);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
struct uart_port *port = &sci_port->port;
|
||||
|
||||
spin_lock_irqsave(&port->lock, flags);
|
||||
port->uartclk = clk_get_rate(sci_port->iclk);
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
||||
return NOTIFY_OK;
|
||||
|
@ -882,21 +862,21 @@ static int sci_request_irq(struct sci_port *port)
|
|||
const char *desc[] = { "SCI Receive Error", "SCI Receive Data Full",
|
||||
"SCI Transmit Data Empty", "SCI Break" };
|
||||
|
||||
if (port->irqs[0] == port->irqs[1]) {
|
||||
if (unlikely(!port->irqs[0]))
|
||||
if (port->cfg->irqs[0] == port->cfg->irqs[1]) {
|
||||
if (unlikely(!port->cfg->irqs[0]))
|
||||
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)) {
|
||||
dev_err(port->port.dev, "Can't allocate IRQ\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
} else {
|
||||
for (i = 0; i < ARRAY_SIZE(handlers); i++) {
|
||||
if (unlikely(!port->irqs[i]))
|
||||
if (unlikely(!port->cfg->irqs[i]))
|
||||
continue;
|
||||
|
||||
if (request_irq(port->irqs[i], handlers[i],
|
||||
if (request_irq(port->cfg->irqs[i], handlers[i],
|
||||
IRQF_DISABLED, desc[i], port)) {
|
||||
dev_err(port->port.dev, "Can't allocate IRQ\n");
|
||||
return -ENODEV;
|
||||
|
@ -911,14 +891,14 @@ static void sci_free_irq(struct sci_port *port)
|
|||
{
|
||||
int i;
|
||||
|
||||
if (port->irqs[0] == port->irqs[1])
|
||||
free_irq(port->irqs[0], port);
|
||||
if (port->cfg->irqs[0] == port->cfg->irqs[1])
|
||||
free_irq(port->cfg->irqs[0], port);
|
||||
else {
|
||||
for (i = 0; i < ARRAY_SIZE(port->irqs); i++) {
|
||||
if (!port->irqs[i])
|
||||
for (i = 0; i < ARRAY_SIZE(port->cfg->irqs); i++) {
|
||||
if (!port->cfg->irqs[i])
|
||||
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)
|
|||
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)
|
||||
{
|
||||
struct dma_chan *chan = s->chan_rx;
|
||||
|
@ -1325,7 +1302,7 @@ static void rx_timer_fn(unsigned long arg)
|
|||
|
||||
if (port->type == PORT_SCIFA || port->type == PORT_SCIFB) {
|
||||
scr &= ~0x4000;
|
||||
enable_irq(s->irqs[1]);
|
||||
enable_irq(s->cfg->irqs[1]);
|
||||
}
|
||||
sci_out(port, SCSCR, scr | SCSCR_RIE);
|
||||
dev_dbg(port->dev, "DMA Rx timed out\n");
|
||||
|
@ -1341,9 +1318,9 @@ static void sci_request_dma(struct uart_port *port)
|
|||
int nent;
|
||||
|
||||
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;
|
||||
|
||||
dma_cap_zero(mask);
|
||||
|
@ -1352,8 +1329,8 @@ static void sci_request_dma(struct uart_port *port)
|
|||
param = &s->param_tx;
|
||||
|
||||
/* Slave ID, e.g., SHDMA_SLAVE_SCIF0_TX */
|
||||
param->slave_id = s->slave_tx;
|
||||
param->dma_dev = s->dma_dev;
|
||||
param->slave_id = s->cfg->dma_slave_tx;
|
||||
param->dma_dev = s->cfg->dma_dev;
|
||||
|
||||
s->cookie_tx = -EINVAL;
|
||||
chan = dma_request_channel(mask, filter, param);
|
||||
|
@ -1381,8 +1358,8 @@ static void sci_request_dma(struct uart_port *port)
|
|||
param = &s->param_rx;
|
||||
|
||||
/* Slave ID, e.g., SHDMA_SLAVE_SCIF0_RX */
|
||||
param->slave_id = s->slave_rx;
|
||||
param->dma_dev = s->dma_dev;
|
||||
param->slave_id = s->cfg->dma_slave_rx;
|
||||
param->dma_dev = s->cfg->dma_dev;
|
||||
|
||||
chan = dma_request_channel(mask, filter, param);
|
||||
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)
|
|||
{
|
||||
struct sci_port *s = to_sci_port(port);
|
||||
|
||||
if (!s->dma_dev)
|
||||
if (!s->cfg->dma_dev)
|
||||
return;
|
||||
|
||||
if (s->chan_tx)
|
||||
|
@ -1435,21 +1412,32 @@ static void sci_free_dma(struct uart_port *port)
|
|||
if (s->chan_rx)
|
||||
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
|
||||
|
||||
static int sci_startup(struct uart_port *port)
|
||||
{
|
||||
struct sci_port *s = to_sci_port(port);
|
||||
int ret;
|
||||
|
||||
dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
|
||||
|
||||
if (s->enable)
|
||||
s->enable(port);
|
||||
|
||||
sci_request_irq(s);
|
||||
#ifdef CONFIG_SERIAL_SH_SCI_DMA
|
||||
ret = sci_request_irq(s);
|
||||
if (unlikely(ret < 0))
|
||||
return ret;
|
||||
|
||||
sci_request_dma(port);
|
||||
#endif
|
||||
|
||||
sci_start_tx(port);
|
||||
sci_start_rx(port);
|
||||
|
||||
|
@ -1464,9 +1452,8 @@ static void sci_shutdown(struct uart_port *port)
|
|||
|
||||
sci_stop_rx(port);
|
||||
sci_stop_tx(port);
|
||||
#ifdef CONFIG_SERIAL_SH_SCI_DMA
|
||||
|
||||
sci_free_dma(port);
|
||||
#endif
|
||||
sci_free_irq(s);
|
||||
|
||||
if (s->disable)
|
||||
|
@ -1491,6 +1478,7 @@ static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps,
|
|||
|
||||
/* Warn, but use a safe default */
|
||||
WARN_ON(1);
|
||||
|
||||
return ((freq + 16 * bps) / (32 * bps) - 1);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
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 {
|
||||
status = sci_in(port, SCxSR);
|
||||
|
@ -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);
|
||||
|
||||
smr_val = sci_in(port, SCSMR) & 3;
|
||||
|
||||
if ((termios->c_cflag & CSIZE) == CS7)
|
||||
smr_val |= 0x40;
|
||||
if (termios->c_cflag & PARENB)
|
||||
|
@ -1540,7 +1532,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
|
|||
sci_out(port, SCSMR, smr_val);
|
||||
|
||||
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 >= 256) {
|
||||
|
@ -1556,7 +1548,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
|
|||
sci_init_pins(port, termios->c_cflag);
|
||||
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
|
||||
/*
|
||||
|
@ -1582,6 +1574,9 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
|
|||
|
||||
if ((termios->c_cflag & CREAD) != 0)
|
||||
sci_start_rx(port);
|
||||
|
||||
if (s->disable)
|
||||
s->disable(port);
|
||||
}
|
||||
|
||||
static const char *sci_type(struct uart_port *port)
|
||||
|
@ -1602,31 +1597,33 @@ static const char *sci_type(struct uart_port *port)
|
|||
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
|
||||
* from platform resource data at such a time that ports begin to
|
||||
* behave more erratically.
|
||||
*/
|
||||
return 64;
|
||||
}
|
||||
|
||||
static int sci_request_port(struct uart_port *port)
|
||||
static int sci_remap_port(struct uart_port *port)
|
||||
{
|
||||
/* Nothing here yet .. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void sci_config_port(struct uart_port *port, int flags)
|
||||
{
|
||||
struct sci_port *s = to_sci_port(port);
|
||||
|
||||
port->type = s->type;
|
||||
unsigned long size = sci_port_size(port);
|
||||
|
||||
/*
|
||||
* Nothing to do if there's already an established membase.
|
||||
*/
|
||||
if (port->membase)
|
||||
return;
|
||||
return 0;
|
||||
|
||||
if (port->flags & UPF_IOREMAP) {
|
||||
port->membase = ioremap_nocache(port->mapbase, 0x40);
|
||||
|
||||
if (IS_ERR(port->membase))
|
||||
port->membase = ioremap_nocache(port->mapbase, size);
|
||||
if (unlikely(!port->membase)) {
|
||||
dev_err(port->dev, "can't remap port#%d\n", port->line);
|
||||
return -ENXIO;
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* 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)
|
|||
*/
|
||||
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)
|
||||
{
|
||||
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;
|
||||
if (ser->baud_base < 2400)
|
||||
/* No paper tape reader for Mitch.. */
|
||||
|
@ -1726,36 +1764,29 @@ static int __devinit sci_init_single(struct platform_device *dev,
|
|||
sci_port->break_timer.function = sci_break_timer;
|
||||
init_timer(&sci_port->break_timer);
|
||||
|
||||
port->mapbase = p->mapbase;
|
||||
port->membase = p->membase;
|
||||
sci_port->cfg = p;
|
||||
|
||||
port->irq = p->irqs[SCIx_TXI_IRQ];
|
||||
port->mapbase = p->mapbase;
|
||||
port->type = p->type;
|
||||
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;
|
||||
sci_port->slave_tx = p->dma_slave_tx;
|
||||
sci_port->slave_rx = p->dma_slave_rx;
|
||||
/*
|
||||
* The UART port needs an IRQ value, so we peg this to the TX IRQ
|
||||
* for the multi-IRQ ports, which is where we are primarily
|
||||
* 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__,
|
||||
p->dma_dev, p->dma_slave_tx, p->dma_slave_rx);
|
||||
#endif
|
||||
if (p->dma_dev)
|
||||
dev_dbg(port->dev, "DMA device %p, tx %d, rx %d\n",
|
||||
p->dma_dev, p->dma_slave_tx, p->dma_slave_rx);
|
||||
|
||||
memcpy(&sci_port->irqs, &p->irqs, sizeof(p->irqs));
|
||||
return 0;
|
||||
}
|
||||
|
||||
#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)
|
||||
{
|
||||
sci_poll_put_char(port, 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,
|
||||
unsigned count)
|
||||
{
|
||||
struct uart_port *port = co->data;
|
||||
struct sci_port *sci_port = to_sci_port(port);
|
||||
struct sci_port *sci_port = &sci_ports[co->index];
|
||||
struct uart_port *port = &sci_port->port;
|
||||
unsigned short bits;
|
||||
|
||||
if (sci_port->enable)
|
||||
|
@ -1797,32 +1828,17 @@ static int __devinit serial_console_setup(struct console *co, char *options)
|
|||
int ret;
|
||||
|
||||
/*
|
||||
* Check whether an invalid uart number has been specified, and
|
||||
* if so, search for the first available port that does have
|
||||
* console support.
|
||||
* Refuse to handle any bogus ports.
|
||||
*/
|
||||
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;
|
||||
|
||||
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)
|
||||
sci_port->enable(port);
|
||||
|
@ -1842,11 +1858,12 @@ static int __devinit serial_console_setup(struct console *co, char *options)
|
|||
|
||||
static struct console serial_console = {
|
||||
.name = "ttySC",
|
||||
.device = serial_console_device,
|
||||
.device = uart_console_device,
|
||||
.write = serial_console_write,
|
||||
.setup = serial_console_setup,
|
||||
.flags = CON_PRINTBUFFER,
|
||||
.index = -1,
|
||||
.data = &sci_uart_driver,
|
||||
};
|
||||
|
||||
static int __init sci_console_init(void)
|
||||
|
@ -1856,14 +1873,39 @@ static int __init sci_console_init(void)
|
|||
}
|
||||
console_initcall(sci_console_init);
|
||||
|
||||
static struct sci_port early_serial_port;
|
||||
static struct console early_serial_console = {
|
||||
.name = "early_ttySC",
|
||||
.write = serial_console_write,
|
||||
.flags = CON_PRINTBUFFER,
|
||||
.index = -1,
|
||||
};
|
||||
|
||||
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 */
|
||||
|
||||
#if defined(CONFIG_SERIAL_SH_SCI_CONSOLE)
|
||||
|
@ -1885,24 +1927,18 @@ static struct uart_driver sci_uart_driver = {
|
|||
.cons = SCI_CONSOLE,
|
||||
};
|
||||
|
||||
|
||||
static int sci_remove(struct platform_device *dev)
|
||||
{
|
||||
struct sh_sci_priv *priv = platform_get_drvdata(dev);
|
||||
struct sci_port *p;
|
||||
unsigned long flags;
|
||||
struct sci_port *port = platform_get_drvdata(dev);
|
||||
|
||||
cpufreq_unregister_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER);
|
||||
cpufreq_unregister_notifier(&port->freq_transition,
|
||||
CPUFREQ_TRANSITION_NOTIFIER);
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
list_for_each_entry(p, &priv->ports, node) {
|
||||
uart_remove_one_port(&sci_uart_driver, &p->port);
|
||||
clk_put(p->iclk);
|
||||
clk_put(p->fclk);
|
||||
}
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
uart_remove_one_port(&sci_uart_driver, &port->port);
|
||||
|
||||
clk_put(port->iclk);
|
||||
clk_put(port->fclk);
|
||||
|
||||
kfree(priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1911,8 +1947,6 @@ static int __devinit sci_probe_single(struct platform_device *dev,
|
|||
struct plat_sci_port *p,
|
||||
struct sci_port *sciport)
|
||||
{
|
||||
struct sh_sci_priv *priv = platform_get_drvdata(dev);
|
||||
unsigned long flags;
|
||||
int ret;
|
||||
|
||||
/* Sanity check */
|
||||
|
@ -1929,68 +1963,35 @@ static int __devinit sci_probe_single(struct platform_device *dev,
|
|||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = 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;
|
||||
return uart_add_one_port(&sci_uart_driver, &sciport->port);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
struct plat_sci_port *p = dev->dev.platform_data;
|
||||
struct sh_sci_priv *priv;
|
||||
int i, ret = -EINVAL;
|
||||
struct sci_port *sp = &sci_ports[dev->id];
|
||||
int ret;
|
||||
|
||||
#ifdef CONFIG_SERIAL_SH_SCI_CONSOLE
|
||||
if (is_early_platform_device(dev)) {
|
||||
if (dev->id == -1)
|
||||
return -ENOTSUPP;
|
||||
early_serial_console.index = dev->id;
|
||||
early_serial_console.data = &early_serial_port.port;
|
||||
sci_init_single(NULL, &early_serial_port, dev->id, p);
|
||||
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
|
||||
/*
|
||||
* If we've come here via earlyprintk initialization, head off to
|
||||
* the special early probe. We don't have sufficient device state
|
||||
* to make it beyond this yet.
|
||||
*/
|
||||
if (is_early_platform_device(dev))
|
||||
return sci_probe_earlyprintk(dev);
|
||||
|
||||
priv = kzalloc(sizeof(*priv), GFP_KERNEL);
|
||||
if (!priv)
|
||||
return -ENOMEM;
|
||||
platform_set_drvdata(dev, sp);
|
||||
|
||||
INIT_LIST_HEAD(&priv->ports);
|
||||
spin_lock_init(&priv->lock);
|
||||
platform_set_drvdata(dev, priv);
|
||||
ret = sci_probe_single(dev, dev->id, p, sp);
|
||||
if (ret)
|
||||
goto err_unreg;
|
||||
|
||||
priv->clk_nb.notifier_call = sci_notifier;
|
||||
cpufreq_register_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER);
|
||||
sp->freq_transition.notifier_call = sci_notifier;
|
||||
|
||||
if (dev->id != -1) {
|
||||
ret = sci_probe_single(dev, dev->id, p, &sci_ports[dev->id]);
|
||||
if (ret)
|
||||
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;
|
||||
}
|
||||
}
|
||||
ret = cpufreq_register_notifier(&sp->freq_transition,
|
||||
CPUFREQ_TRANSITION_NOTIFIER);
|
||||
if (unlikely(ret < 0))
|
||||
goto err_unreg;
|
||||
|
||||
#ifdef CONFIG_SH_STANDARD_BIOS
|
||||
sh_bios_gdb_detach();
|
||||
|
@ -2005,28 +2006,20 @@ static int __devinit sci_probe(struct platform_device *dev)
|
|||
|
||||
static int sci_suspend(struct device *dev)
|
||||
{
|
||||
struct sh_sci_priv *priv = dev_get_drvdata(dev);
|
||||
struct sci_port *p;
|
||||
unsigned long flags;
|
||||
struct sci_port *sport = dev_get_drvdata(dev);
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
list_for_each_entry(p, &priv->ports, node)
|
||||
uart_suspend_port(&sci_uart_driver, &p->port);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
if (sport)
|
||||
uart_suspend_port(&sci_uart_driver, &sport->port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sci_resume(struct device *dev)
|
||||
{
|
||||
struct sh_sci_priv *priv = dev_get_drvdata(dev);
|
||||
struct sci_port *p;
|
||||
unsigned long flags;
|
||||
struct sci_port *sport = dev_get_drvdata(dev);
|
||||
|
||||
spin_lock_irqsave(&priv->lock, flags);
|
||||
list_for_each_entry(p, &priv->ports, node)
|
||||
uart_resume_port(&sci_uart_driver, &p->port);
|
||||
spin_unlock_irqrestore(&priv->lock, flags);
|
||||
if (sport)
|
||||
uart_resume_port(&sci_uart_driver, &sport->port);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -54,9 +54,6 @@
|
|||
# define PBCR 0xa4050102
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH7343)
|
||||
# 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)
|
||||
# define PADR 0xA4050120
|
||||
# define PSDR 0xA405013e
|
||||
|
@ -69,77 +66,42 @@
|
|||
# define SCIF_ORER 0x0001 /* overrun error bit */
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH7723)
|
||||
# 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 */
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH7724)
|
||||
# define SCIF_ORER 0x0001 /* overrun error bit */
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH4_202)
|
||||
# define SCSPTR2 0xffe80020 /* 16 bit SCIF */
|
||||
# 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)
|
||||
# define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port)
|
||||
#elif defined(CONFIG_H8S2678)
|
||||
# define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port)
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH7757)
|
||||
# define SCSPTR0 0xfe4b0020
|
||||
# define SCSPTR1 0xfe4b0020
|
||||
# define SCSPTR2 0xfe4b0020
|
||||
# define SCIF_ORER 0x0001
|
||||
# define SCIF_ONLY
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH7763)
|
||||
# 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 */
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH7770)
|
||||
# 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 */
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH7780)
|
||||
# define SCSPTR0 0xffe00024 /* 16 bit SCIF */
|
||||
# define SCSPTR1 0xffe10024 /* 16 bit SCIF */
|
||||
# define SCIF_ORER 0x0001 /* Overrun error bit */
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH7785) || \
|
||||
defined(CONFIG_CPU_SUBTYPE_SH7786)
|
||||
# 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 */
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH7201) || \
|
||||
defined(CONFIG_CPU_SUBTYPE_SH7203) || \
|
||||
defined(CONFIG_CPU_SUBTYPE_SH7206) || \
|
||||
defined(CONFIG_CPU_SUBTYPE_SH7263)
|
||||
# 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)
|
||||
# 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 */
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SHX3)
|
||||
# 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 */
|
||||
#else
|
||||
# error CPU subtype not defined
|
||||
|
@ -411,7 +373,6 @@ SCIF_FNS(SCSPTR, 0, 0, 0x24, 16)
|
|||
SCIF_FNS(SCLSR, 0, 0, 0x28, 16)
|
||||
#elif defined(CONFIG_CPU_SUBTYPE_SH7763)
|
||||
SCIF_FNS(SCFDR, 0, 0, 0x1C, 16)
|
||||
SCIF_FNS(SCSPTR2, 0, 0, 0x20, 16)
|
||||
SCIF_FNS(SCTFDR, 0x0e, 16, 0x1C, 16)
|
||||
SCIF_FNS(SCRFDR, 0x0e, 16, 0x20, 16)
|
||||
SCIF_FNS(SCSPTR, 0, 0, 0x24, 16)
|
||||
|
|
|
@ -1083,14 +1083,6 @@ config SH_WDT
|
|||
To compile this driver as a module, choose M here: the
|
||||
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
|
||||
|
||||
# SPARC64 Architecture
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
* drivers/char/watchdog/shwdt.c
|
||||
* drivers/watchdog/shwdt.c
|
||||
*
|
||||
* 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
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/moduleparam.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/miscdevice.h>
|
||||
|
@ -28,11 +29,12 @@
|
|||
#include <linux/ioport.h>
|
||||
#include <linux/fs.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/uaccess.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
|
||||
|
@ -62,37 +64,36 @@
|
|||
* misses its deadline, the kernel timer will allow the WDT to overflow.
|
||||
*/
|
||||
static int clock_division_ratio = WTCSR_CKS_4096;
|
||||
|
||||
#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 char shwdt_expect_close;
|
||||
static DEFINE_TIMER(timer, sh_wdt_ping, 0, 0);
|
||||
static unsigned long next_heartbeat;
|
||||
static struct platform_device *sh_wdt_dev;
|
||||
static DEFINE_SPINLOCK(shwdt_lock);
|
||||
|
||||
#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */
|
||||
static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */
|
||||
|
||||
static int nowayout = WATCHDOG_NOWAYOUT;
|
||||
static unsigned long next_heartbeat;
|
||||
|
||||
/**
|
||||
* sh_wdt_start - Start the Watchdog
|
||||
*
|
||||
* Starts the watchdog.
|
||||
*/
|
||||
static void sh_wdt_start(void)
|
||||
struct sh_wdt {
|
||||
void __iomem *base;
|
||||
struct device *dev;
|
||||
|
||||
struct timer_list timer;
|
||||
|
||||
unsigned long enabled;
|
||||
char expect_close;
|
||||
};
|
||||
|
||||
static void sh_wdt_start(struct sh_wdt *wdt)
|
||||
{
|
||||
__u8 csr;
|
||||
unsigned long flags;
|
||||
u8 csr;
|
||||
|
||||
spin_lock_irqsave(&shwdt_lock, flags);
|
||||
|
||||
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 |= WTCSR_WT | clock_division_ratio;
|
||||
|
@ -114,15 +115,6 @@ static void sh_wdt_start(void)
|
|||
sh_wdt_write_csr(csr);
|
||||
|
||||
#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 &= ~RSTCSR_RSTS;
|
||||
sh_wdt_write_rstcsr(csr);
|
||||
|
@ -130,30 +122,23 @@ static void sh_wdt_start(void)
|
|||
spin_unlock_irqrestore(&shwdt_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* sh_wdt_stop - Stop the Watchdog
|
||||
* Stops the watchdog.
|
||||
*/
|
||||
static void sh_wdt_stop(void)
|
||||
static void sh_wdt_stop(struct sh_wdt *wdt)
|
||||
{
|
||||
__u8 csr;
|
||||
unsigned long flags;
|
||||
u8 csr;
|
||||
|
||||
spin_lock_irqsave(&shwdt_lock, flags);
|
||||
|
||||
del_timer(&timer);
|
||||
del_timer(&wdt->timer);
|
||||
|
||||
csr = sh_wdt_read_csr();
|
||||
csr &= ~WTCSR_TME;
|
||||
sh_wdt_write_csr(csr);
|
||||
|
||||
spin_unlock_irqrestore(&shwdt_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
static inline void sh_wdt_keepalive(struct sh_wdt *wdt)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
|
@ -162,10 +147,6 @@ static inline void sh_wdt_keepalive(void)
|
|||
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)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
@ -179,19 +160,14 @@ static int sh_wdt_set_heartbeat(int t)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* sh_wdt_ping - Ping the Watchdog
|
||||
* @data: Unused
|
||||
*
|
||||
* Clears overflow bit, resets timer counter.
|
||||
*/
|
||||
static void sh_wdt_ping(unsigned long data)
|
||||
{
|
||||
struct sh_wdt *wdt = (struct sh_wdt *)data;
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&shwdt_lock, flags);
|
||||
if (time_before(jiffies, next_heartbeat)) {
|
||||
__u8 csr;
|
||||
u8 csr;
|
||||
|
||||
csr = sh_wdt_read_csr();
|
||||
csr &= ~WTCSR_IOVF;
|
||||
|
@ -199,148 +175,76 @@ static void sh_wdt_ping(unsigned long data)
|
|||
|
||||
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
|
||||
printk(KERN_WARNING PFX "Heartbeat lost! Will not ping "
|
||||
"the watchdog\n");
|
||||
dev_warn(wdt->dev, "Heartbeat lost! Will not ping "
|
||||
"the watchdog\n");
|
||||
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)
|
||||
{
|
||||
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;
|
||||
if (nowayout)
|
||||
__module_get(THIS_MODULE);
|
||||
|
||||
sh_wdt_start();
|
||||
file->private_data = wdt;
|
||||
|
||||
sh_wdt_start(wdt);
|
||||
|
||||
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)
|
||||
{
|
||||
if (shwdt_expect_close == 42) {
|
||||
sh_wdt_stop();
|
||||
struct sh_wdt *wdt = file->private_data;
|
||||
|
||||
if (wdt->expect_close == 42) {
|
||||
sh_wdt_stop(wdt);
|
||||
} else {
|
||||
printk(KERN_CRIT PFX "Unexpected close, not "
|
||||
"stopping watchdog!\n");
|
||||
sh_wdt_keepalive();
|
||||
dev_crit(wdt->dev, "Unexpected close, not "
|
||||
"stopping watchdog!\n");
|
||||
sh_wdt_keepalive(wdt);
|
||||
}
|
||||
|
||||
clear_bit(0, &shwdt_is_open);
|
||||
shwdt_expect_close = 0;
|
||||
clear_bit(0, &wdt->enabled);
|
||||
wdt->expect_close = 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,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct sh_wdt *wdt = file->private_data;
|
||||
|
||||
if (count) {
|
||||
if (!nowayout) {
|
||||
size_t i;
|
||||
|
||||
shwdt_expect_close = 0;
|
||||
wdt->expect_close = 0;
|
||||
|
||||
for (i = 0; i != count; i++) {
|
||||
char c;
|
||||
if (get_user(c, buf + i))
|
||||
return -EFAULT;
|
||||
if (c == 'V')
|
||||
shwdt_expect_close = 42;
|
||||
wdt->expect_close = 42;
|
||||
}
|
||||
}
|
||||
sh_wdt_keepalive();
|
||||
sh_wdt_keepalive(wdt);
|
||||
}
|
||||
|
||||
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,
|
||||
unsigned long arg)
|
||||
{
|
||||
struct sh_wdt *wdt = file->private_data;
|
||||
int new_heartbeat;
|
||||
int options, retval = -EINVAL;
|
||||
|
||||
|
@ -356,18 +260,18 @@ static long sh_wdt_ioctl(struct file *file, unsigned int cmd,
|
|||
return -EFAULT;
|
||||
|
||||
if (options & WDIOS_DISABLECARD) {
|
||||
sh_wdt_stop();
|
||||
sh_wdt_stop(wdt);
|
||||
retval = 0;
|
||||
}
|
||||
|
||||
if (options & WDIOS_ENABLECARD) {
|
||||
sh_wdt_start();
|
||||
sh_wdt_start(wdt);
|
||||
retval = 0;
|
||||
}
|
||||
|
||||
return retval;
|
||||
case WDIOC_KEEPALIVE:
|
||||
sh_wdt_keepalive();
|
||||
sh_wdt_keepalive(wdt);
|
||||
return 0;
|
||||
case WDIOC_SETTIMEOUT:
|
||||
if (get_user(new_heartbeat, (int *)arg))
|
||||
|
@ -376,7 +280,7 @@ static long sh_wdt_ioctl(struct file *file, unsigned int cmd,
|
|||
if (sh_wdt_set_heartbeat(new_heartbeat))
|
||||
return -EINVAL;
|
||||
|
||||
sh_wdt_keepalive();
|
||||
sh_wdt_keepalive(wdt);
|
||||
/* Fall */
|
||||
case WDIOC_GETTIMEOUT:
|
||||
return put_user(heartbeat, (int *)arg);
|
||||
|
@ -386,20 +290,13 @@ static long sh_wdt_ioctl(struct file *file, unsigned int cmd,
|
|||
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,
|
||||
unsigned long code, void *unused)
|
||||
{
|
||||
struct sh_wdt *wdt = platform_get_drvdata(sh_wdt_dev);
|
||||
|
||||
if (code == SYS_DOWN || code == SYS_HALT)
|
||||
sh_wdt_stop();
|
||||
sh_wdt_stop(wdt);
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
@ -411,7 +308,6 @@ static const struct file_operations sh_wdt_fops = {
|
|||
.unlocked_ioctl = sh_wdt_ioctl,
|
||||
.open = sh_wdt_open,
|
||||
.release = sh_wdt_close,
|
||||
.mmap = sh_wdt_mmap,
|
||||
};
|
||||
|
||||
static const struct watchdog_info sh_wdt_info = {
|
||||
|
@ -431,66 +327,148 @@ static struct miscdevice sh_wdt_miscdev = {
|
|||
.fops = &sh_wdt_fops,
|
||||
};
|
||||
|
||||
/**
|
||||
* sh_wdt_init - Initialize module
|
||||
* Registers the device and notifier handler. Actual device
|
||||
* initialization is handled by sh_wdt_open().
|
||||
*/
|
||||
static int __devinit sh_wdt_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct sh_wdt *wdt;
|
||||
struct resource *res;
|
||||
int rc;
|
||||
|
||||
/*
|
||||
* As this driver only covers the global watchdog case, reject
|
||||
* any attempts to register per-CPU watchdogs.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
wdt->dev = &pdev->dev;
|
||||
|
||||
wdt->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
|
||||
if (unlikely(!wdt->base)) {
|
||||
rc = -ENXIO;
|
||||
goto out_err;
|
||||
}
|
||||
|
||||
rc = register_reboot_notifier(&sh_wdt_notifier);
|
||||
if (unlikely(rc)) {
|
||||
dev_err(&pdev->dev,
|
||||
"Can't register reboot notifier (err=%d)\n", rc);
|
||||
goto out_unmap;
|
||||
}
|
||||
|
||||
sh_wdt_miscdev.parent = wdt->dev;
|
||||
|
||||
rc = misc_register(&sh_wdt_miscdev);
|
||||
if (unlikely(rc)) {
|
||||
dev_err(&pdev->dev,
|
||||
"Can't register miscdev on minor=%d (err=%d)\n",
|
||||
sh_wdt_miscdev.minor, rc);
|
||||
goto out_unreg;
|
||||
}
|
||||
|
||||
init_timer(&wdt->timer);
|
||||
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;
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
|
||||
sh_wdt_dev = NULL;
|
||||
|
||||
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 (clock_division_ratio < 0x5 || clock_division_ratio > 0x7) {
|
||||
if (unlikely(clock_division_ratio < 0x5 ||
|
||||
clock_division_ratio > 0x7)) {
|
||||
clock_division_ratio = WTCSR_CKS_4096;
|
||||
printk(KERN_INFO PFX
|
||||
"clock_division_ratio value must be 0x5<=x<=0x7, using %d\n",
|
||||
clock_division_ratio);
|
||||
|
||||
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;
|
||||
printk(KERN_INFO PFX
|
||||
"heartbeat value must be 1<=x<=3600, using %d\n",
|
||||
heartbeat);
|
||||
|
||||
pr_info("%s: heartbeat value must be 1<=x<=3600, using %d\n",
|
||||
DRV_NAME, heartbeat);
|
||||
}
|
||||
|
||||
rc = register_reboot_notifier(&sh_wdt_notifier);
|
||||
if (unlikely(rc)) {
|
||||
printk(KERN_ERR PFX
|
||||
"Can't register reboot notifier (err=%d)\n", rc);
|
||||
return rc;
|
||||
}
|
||||
pr_info("%s: configured with heartbeat=%d sec (nowayout=%d)\n",
|
||||
DRV_NAME, heartbeat, nowayout);
|
||||
|
||||
rc = misc_register(&sh_wdt_miscdev);
|
||||
if (unlikely(rc)) {
|
||||
printk(KERN_ERR PFX
|
||||
"Can't register miscdev on minor=%d (err=%d)\n",
|
||||
sh_wdt_miscdev.minor, rc);
|
||||
unregister_reboot_notifier(&sh_wdt_notifier);
|
||||
return rc;
|
||||
}
|
||||
|
||||
printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n",
|
||||
heartbeat, nowayout);
|
||||
|
||||
return 0;
|
||||
return platform_driver_register(&sh_wdt_driver);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
misc_deregister(&sh_wdt_miscdev);
|
||||
unregister_reboot_notifier(&sh_wdt_notifier);
|
||||
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_DESCRIPTION("SuperH watchdog driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("platform:" DRV_NAME);
|
||||
MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
|
||||
|
||||
module_param(clock_division_ratio, int, 0);
|
||||
|
@ -507,6 +485,3 @@ module_param(nowayout, int, 0);
|
|||
MODULE_PARM_DESC(nowayout,
|
||||
"Watchdog cannot be stopped once started (default="
|
||||
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
|
||||
|
||||
module_init(sh_wdt_init);
|
||||
module_exit(sh_wdt_exit);
|
||||
|
|
|
@ -34,28 +34,32 @@ enum {
|
|||
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;
|
||||
|
||||
/*
|
||||
* Platform device specific platform_data struct
|
||||
*/
|
||||
struct plat_sci_port {
|
||||
void __iomem *membase; /* io cookie */
|
||||
unsigned long mapbase; /* resource base */
|
||||
unsigned int irqs[SCIx_NR_IRQS]; /* ERI, RXI, TXI, BRI */
|
||||
unsigned int type; /* SCI / SCIF / IRDA */
|
||||
upf_t flags; /* UPF_* flags */
|
||||
char *clk; /* clock string */
|
||||
|
||||
unsigned int scbrr_algo_id; /* SCBRR calculation algo */
|
||||
unsigned int scscr; /* SCSCR initialization */
|
||||
|
||||
struct device *dma_dev;
|
||||
|
||||
#ifdef CONFIG_SERIAL_SH_SCI_DMA
|
||||
unsigned int dma_slave_tx;
|
||||
unsigned int dma_slave_rx;
|
||||
#endif
|
||||
unsigned int dma_slave_tx;
|
||||
unsigned int dma_slave_rx;
|
||||
};
|
||||
|
||||
#endif /* __LINUX_SERIAL_SCI_H */
|
||||
|
|
|
@ -34,7 +34,7 @@ config GCOV_KERNEL
|
|||
config GCOV_PROFILE_ALL
|
||||
bool "Profile entire Kernel"
|
||||
depends on GCOV_KERNEL
|
||||
depends on S390 || X86 || (PPC && EXPERIMENTAL) || MICROBLAZE
|
||||
depends on SUPERH || S390 || X86 || (PPC && EXPERIMENTAL) || MICROBLAZE
|
||||
default n
|
||||
---help---
|
||||
This options activates profiling for the entire kernel.
|
||||
|
|
Loading…
Reference in a new issue