]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
Merge branch 'sh/urgent' into sh-latest
authorPaul Mundt <lethal@linux-sh.org>
Tue, 10 Jan 2012 07:37:52 +0000 (16:37 +0900)
committerPaul Mundt <lethal@linux-sh.org>
Tue, 10 Jan 2012 07:37:52 +0000 (16:37 +0900)
15 files changed:
arch/arm/mach-shmobile/clock-sh7372.c
arch/arm/mach-shmobile/clock-sh73a0.c
arch/arm/mach-shmobile/include/mach/common.h
arch/sh/boards/board-sh7757lcr.c
arch/sh/include/cpu-sh4/cpu/sh7724.h
arch/sh/kernel/cpu/sh4a/clock-sh7723.c
arch/sh/kernel/cpu/sh4a/clock-sh7724.c
arch/sh/kernel/cpu/sh4a/clock-sh7757.c
drivers/sh/clk/core.c
drivers/sh/clk/cpg.c
drivers/sh/pfc.c
drivers/tty/serial/sh-sci.c
include/linux/serial_sci.h
include/linux/sh_clk.h
include/linux/sh_pfc.h

index 995a9c3aec8fbe60da9c78f3dba9835d20db9003..e349c22a0d71c93c54e49466549814795c80b77b 100644 (file)
@@ -411,11 +411,11 @@ static struct clk *fsibckcr_parent[] = {
 };
 
 static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = {
-       [DIV6_HDMI] = SH_CLK_DIV6_EXT(&pllc1_div2_clk, HDMICKCR, 0,
+       [DIV6_HDMI] = SH_CLK_DIV6_EXT(HDMICKCR, 0,
                                      hdmi_parent, ARRAY_SIZE(hdmi_parent), 6, 2),
-       [DIV6_FSIA] = SH_CLK_DIV6_EXT(&pllc1_div2_clk, FSIACKCR, 0,
+       [DIV6_FSIA] = SH_CLK_DIV6_EXT(FSIACKCR, 0,
                                      fsiackcr_parent, ARRAY_SIZE(fsiackcr_parent), 6, 2),
-       [DIV6_FSIB] = SH_CLK_DIV6_EXT(&pllc1_div2_clk, FSIBCKCR, 0,
+       [DIV6_FSIB] = SH_CLK_DIV6_EXT(FSIBCKCR, 0,
                                      fsibckcr_parent, ARRAY_SIZE(fsibckcr_parent), 6, 2),
 };
 
index 1370a89ca358ba548c80ae5ed3ec29b52156b501..34944d01bf1ed99db00a49f4b9845271ddce3a3e 100644 (file)
@@ -92,6 +92,24 @@ static struct clk_ops div2_clk_ops = {
        .recalc         = div2_recalc,
 };
 
+static unsigned long div7_recalc(struct clk *clk)
+{
+       return clk->parent->rate / 7;
+}
+
+static struct clk_ops div7_clk_ops = {
+       .recalc         = div7_recalc,
+};
+
+static unsigned long div13_recalc(struct clk *clk)
+{
+       return clk->parent->rate / 13;
+}
+
+static struct clk_ops div13_clk_ops = {
+       .recalc         = div13_recalc,
+};
+
 /* Divide extal1 by two */
 static struct clk extal1_div2_clk = {
        .ops            = &div2_clk_ops,
@@ -174,12 +192,29 @@ static struct clk pll3_clk = {
        .enable_bit     = 3,
 };
 
-/* Divide PLL1 by two */
+/* Divide PLL */
 static struct clk pll1_div2_clk = {
        .ops            = &div2_clk_ops,
        .parent         = &pll1_clk,
 };
 
+static struct clk pll1_div7_clk = {
+       .ops            = &div7_clk_ops,
+       .parent         = &pll1_clk,
+};
+
+static struct clk pll1_div13_clk = {
+       .ops            = &div13_clk_ops,
+       .parent         = &pll1_clk,
+};
+
+/* External input clock */
+struct clk sh73a0_extcki_clk = {
+};
+
+struct clk sh73a0_extalr_clk = {
+};
+
 static struct clk *main_clks[] = {
        &r_clk,
        &sh73a0_extal1_clk,
@@ -193,6 +228,10 @@ static struct clk *main_clks[] = {
        &pll2_clk,
        &pll3_clk,
        &pll1_div2_clk,
+       &pll1_div7_clk,
+       &pll1_div13_clk,
+       &sh73a0_extcki_clk,
+       &sh73a0_extalr_clk,
 };
 
 static void div4_kick(struct clk *clk)
@@ -246,27 +285,84 @@ enum { DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_ZB1,
        DIV6_DSIT, DIV6_DSI0P, DIV6_DSI1P,
        DIV6_NR };
 
+static struct clk *vck_parent[8] = {
+       [0] = &pll1_div2_clk,
+       [1] = &pll2_clk,
+       [2] = &sh73a0_extcki_clk,
+       [3] = &sh73a0_extal2_clk,
+       [4] = &main_div2_clk,
+       [5] = &sh73a0_extalr_clk,
+       [6] = &main_clk,
+};
+
+static struct clk *pll_parent[4] = {
+       [0] = &pll1_div2_clk,
+       [1] = &pll2_clk,
+       [2] = &pll1_div13_clk,
+};
+
+static struct clk *hsi_parent[4] = {
+       [0] = &pll1_div2_clk,
+       [1] = &pll2_clk,
+       [2] = &pll1_div7_clk,
+};
+
+static struct clk *pll_extal2_parent[] = {
+       [0] = &pll1_div2_clk,
+       [1] = &pll2_clk,
+       [2] = &sh73a0_extal2_clk,
+       [3] = &sh73a0_extal2_clk,
+};
+
+static struct clk *dsi_parent[8] = {
+       [0] = &pll1_div2_clk,
+       [1] = &pll2_clk,
+       [2] = &main_clk,
+       [3] = &sh73a0_extal2_clk,
+       [4] = &sh73a0_extcki_clk,
+};
+
 static struct clk div6_clks[DIV6_NR] = {
-       [DIV6_VCK1] = SH_CLK_DIV6(&pll1_div2_clk, VCLKCR1, 0),
-       [DIV6_VCK2] = SH_CLK_DIV6(&pll1_div2_clk, VCLKCR2, 0),
-       [DIV6_VCK3] = SH_CLK_DIV6(&pll1_div2_clk, VCLKCR3, 0),
-       [DIV6_ZB1] = SH_CLK_DIV6(&pll1_div2_clk, ZBCKCR, CLK_ENABLE_ON_INIT),
-       [DIV6_FLCTL] = SH_CLK_DIV6(&pll1_div2_clk, FLCKCR, 0),
-       [DIV6_SDHI0] = SH_CLK_DIV6(&pll1_div2_clk, SD0CKCR, 0),
-       [DIV6_SDHI1] = SH_CLK_DIV6(&pll1_div2_clk, SD1CKCR, 0),
-       [DIV6_SDHI2] = SH_CLK_DIV6(&pll1_div2_clk, SD2CKCR, 0),
-       [DIV6_FSIA] = SH_CLK_DIV6(&pll1_div2_clk, FSIACKCR, 0),
-       [DIV6_FSIB] = SH_CLK_DIV6(&pll1_div2_clk, FSIBCKCR, 0),
-       [DIV6_SUB] = SH_CLK_DIV6(&sh73a0_extal2_clk, SUBCKCR, 0),
-       [DIV6_SPUA] = SH_CLK_DIV6(&pll1_div2_clk, SPUACKCR, 0),
-       [DIV6_SPUV] = SH_CLK_DIV6(&pll1_div2_clk, SPUVCKCR, 0),
-       [DIV6_MSU] = SH_CLK_DIV6(&pll1_div2_clk, MSUCKCR, 0),
-       [DIV6_HSI] = SH_CLK_DIV6(&pll1_div2_clk, HSICKCR, 0),
-       [DIV6_MFG1] = SH_CLK_DIV6(&pll1_div2_clk, MFCK1CR, 0),
-       [DIV6_MFG2] = SH_CLK_DIV6(&pll1_div2_clk, MFCK2CR, 0),
-       [DIV6_DSIT] = SH_CLK_DIV6(&pll1_div2_clk, DSITCKCR, 0),
-       [DIV6_DSI0P] = SH_CLK_DIV6(&pll1_div2_clk, DSI0PCKCR, 0),
-       [DIV6_DSI1P] = SH_CLK_DIV6(&pll1_div2_clk, DSI1PCKCR, 0),
+       [DIV6_VCK1] = SH_CLK_DIV6_EXT(VCLKCR1, 0,
+                       vck_parent, ARRAY_SIZE(vck_parent), 12, 3),
+       [DIV6_VCK2] = SH_CLK_DIV6_EXT(VCLKCR2, 0,
+                       vck_parent, ARRAY_SIZE(vck_parent), 12, 3),
+       [DIV6_VCK3] = SH_CLK_DIV6_EXT(VCLKCR3, 0,
+                       vck_parent, ARRAY_SIZE(vck_parent), 12, 3),
+       [DIV6_ZB1] = SH_CLK_DIV6_EXT(ZBCKCR, CLK_ENABLE_ON_INIT,
+                       pll_parent, ARRAY_SIZE(pll_parent), 7, 1),
+       [DIV6_FLCTL] = SH_CLK_DIV6_EXT(FLCKCR, 0,
+                       pll_parent, ARRAY_SIZE(pll_parent), 7, 1),
+       [DIV6_SDHI0] = SH_CLK_DIV6_EXT(SD0CKCR, 0,
+                       pll_parent, ARRAY_SIZE(pll_parent), 6, 2),
+       [DIV6_SDHI1] = SH_CLK_DIV6_EXT(SD1CKCR, 0,
+                       pll_parent, ARRAY_SIZE(pll_parent), 6, 2),
+       [DIV6_SDHI2] = SH_CLK_DIV6_EXT(SD2CKCR, 0,
+                       pll_parent, ARRAY_SIZE(pll_parent), 6, 2),
+       [DIV6_FSIA] = SH_CLK_DIV6_EXT(FSIACKCR, 0,
+                       pll_parent, ARRAY_SIZE(pll_parent), 6, 1),
+       [DIV6_FSIB] = SH_CLK_DIV6_EXT(FSIBCKCR, 0,
+                       pll_parent, ARRAY_SIZE(pll_parent), 6, 1),
+       [DIV6_SUB] = SH_CLK_DIV6_EXT(SUBCKCR, 0,
+                       pll_extal2_parent, ARRAY_SIZE(pll_extal2_parent), 6, 2),
+       [DIV6_SPUA] = SH_CLK_DIV6_EXT(SPUACKCR, 0,
+                       pll_extal2_parent, ARRAY_SIZE(pll_extal2_parent), 6, 2),
+       [DIV6_SPUV] = SH_CLK_DIV6_EXT(SPUVCKCR, 0,
+                       pll_extal2_parent, ARRAY_SIZE(pll_extal2_parent), 6, 2),
+       [DIV6_MSU] = SH_CLK_DIV6_EXT(MSUCKCR, 0,
+                       pll_parent, ARRAY_SIZE(pll_parent), 7, 1),
+       [DIV6_HSI] = SH_CLK_DIV6_EXT(HSICKCR, 0,
+                       hsi_parent, ARRAY_SIZE(hsi_parent), 6, 2),
+       [DIV6_MFG1] = SH_CLK_DIV6_EXT(MFCK1CR, 0,
+                       pll_parent, ARRAY_SIZE(pll_parent), 7, 1),
+       [DIV6_MFG2] = SH_CLK_DIV6_EXT(MFCK2CR, 0,
+                       pll_parent, ARRAY_SIZE(pll_parent), 7, 1),
+       [DIV6_DSIT] = SH_CLK_DIV6_EXT(DSITCKCR, 0,
+                       pll_parent, ARRAY_SIZE(pll_parent), 7, 1),
+       [DIV6_DSI0P] = SH_CLK_DIV6_EXT(DSI0PCKCR, 0,
+                       dsi_parent, ARRAY_SIZE(dsi_parent), 12, 3),
+       [DIV6_DSI1P] = SH_CLK_DIV6_EXT(DSI1PCKCR, 0,
+                       dsi_parent, ARRAY_SIZE(dsi_parent), 12, 3),
 };
 
 enum { MSTP001,
@@ -403,7 +499,7 @@ void __init sh73a0_clock_init(void)
                ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
 
        if (!ret)
-               ret = sh_clk_div6_register(div6_clks, DIV6_NR);
+               ret = sh_clk_div6_reparent_register(div6_clks, DIV6_NR);
 
        if (!ret)
                ret = sh_clk_mstp32_register(mstp_clks, MSTP_NR);
index be78a2c73db4784a598f180b076cc239e693e0c9..13a18d343ecbc090fd847e66ff2d8f030a75b0bc 100644 (file)
@@ -46,6 +46,8 @@ extern void sh73a0_clock_init(void);
 extern void sh73a0_pinmux_init(void);
 extern struct clk sh73a0_extal1_clk;
 extern struct clk sh73a0_extal2_clk;
+extern struct clk sh73a0_extcki_clk;
+extern struct clk sh73a0_extalr_clk;
 
 extern unsigned int sh73a0_get_core_count(void);
 extern void sh73a0_secondary_init(unsigned int cpu);
index 895e337c79b60ed7477f754f968ca80a9a52d754..0838154dd2168bdd2d51b0fe3ebb33e590eca70f 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/mmc/sh_mmcif.h>
 #include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/sh_eth.h>
+#include <linux/usb/renesas_usbhs.h>
 #include <cpu/sh7757.h>
 #include <asm/heartbeat.h>
 
@@ -264,6 +265,43 @@ static struct platform_device sdhi_device = {
        },
 };
 
+static int usbhs0_get_id(struct platform_device *pdev)
+{
+       return USBHS_GADGET;
+}
+
+static struct renesas_usbhs_platform_info usb0_data = {
+       .platform_callback = {
+               .get_id = usbhs0_get_id,
+       },
+       .driver_param = {
+               .buswait_bwait = 5,
+       }
+};
+
+static struct resource usb0_resources[] = {
+       [0] = {
+               .start  = 0xfe450000,
+               .end    = 0xfe4501ff,
+               .flags  = IORESOURCE_MEM,
+       },
+       [1] = {
+               .start  = 50,
+               .end    = 50,
+               .flags  = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device usb0_device = {
+       .name           = "renesas_usbhs",
+       .id             = 0,
+       .dev = {
+               .platform_data          = &usb0_data,
+       },
+       .num_resources  = ARRAY_SIZE(usb0_resources),
+       .resource       = usb0_resources,
+};
+
 static struct platform_device *sh7757lcr_devices[] __initdata = {
        &heartbeat_device,
        &sh7757_eth0_device,
@@ -272,6 +310,7 @@ static struct platform_device *sh7757lcr_devices[] __initdata = {
        &sh7757_eth_giga1_device,
        &sh_mmcif_device,
        &sdhi_device,
+       &usb0_device,
 };
 
 static struct flash_platform_data spi_flash_data = {
index cbc47e6bcab5474b4c675af5600da0c66da1883e..36ce466cbf071b49cd02695bc702938394387447 100644 (file)
@@ -314,5 +314,6 @@ enum {
 
 extern struct clk sh7724_fsimcka_clk;
 extern struct clk sh7724_fsimckb_clk;
+extern struct clk sh7724_dv_clki;
 
 #endif /* __ASM_SH7724_H__ */
index 3cc3827380e3251c1d053c1a8ea8431d49a831b3..f254166e1f3b414ddfddd873015493487395337d 100644 (file)
@@ -233,73 +233,10 @@ static struct clk_lookup lookups[] = {
        CLKDEV_CON_ID("sh0", &mstp_clks[HWBLK_SHYWAY]),
        CLKDEV_CON_ID("hudi0", &mstp_clks[HWBLK_HUDI]),
        CLKDEV_CON_ID("ubc0", &mstp_clks[HWBLK_UBC]),
-       {
-               /* TMU0 */
-               .dev_id         = "sh_tmu.0",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[HWBLK_TMU0],
-       }, {
-               /* TMU1 */
-               .dev_id         = "sh_tmu.1",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[HWBLK_TMU0],
-       }, {
-               /* TMU2 */
-               .dev_id         = "sh_tmu.2",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[HWBLK_TMU0],
-       },
        CLKDEV_CON_ID("cmt_fck", &mstp_clks[HWBLK_CMT]),
        CLKDEV_CON_ID("rwdt0", &mstp_clks[HWBLK_RWDT]),
        CLKDEV_CON_ID("dmac1", &mstp_clks[HWBLK_DMAC1]),
-       {
-               /* TMU3 */
-               .dev_id         = "sh_tmu.3",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[HWBLK_TMU1],
-       }, {
-               /* TMU4 */
-               .dev_id         = "sh_tmu.4",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[HWBLK_TMU1],
-       }, {
-               /* TMU5 */
-               .dev_id         = "sh_tmu.5",
-               .con_id         = "tmu_fck",
-               .clk            = &mstp_clks[HWBLK_TMU1],
-       },
        CLKDEV_CON_ID("flctl0", &mstp_clks[HWBLK_FLCTL]),
-       {
-               /* SCIF0 */
-               .dev_id         = "sh-sci.0",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[HWBLK_SCIF0],
-       }, {
-               /* SCIF1 */
-               .dev_id         = "sh-sci.1",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[HWBLK_SCIF1],
-       }, {
-               /* SCIF2 */
-               .dev_id         = "sh-sci.2",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[HWBLK_SCIF2],
-       }, {
-               /* SCIF3 */
-               .dev_id         = "sh-sci.3",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[HWBLK_SCIF3],
-       }, {
-               /* SCIF4 */
-               .dev_id         = "sh-sci.4",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[HWBLK_SCIF4],
-       }, {
-               /* SCIF5 */
-               .dev_id         = "sh-sci.5",
-               .con_id         = "sci_fck",
-               .clk            = &mstp_clks[HWBLK_SCIF5],
-       },
        CLKDEV_CON_ID("msiof0", &mstp_clks[HWBLK_MSIOF0]),
        CLKDEV_CON_ID("msiof1", &mstp_clks[HWBLK_MSIOF1]),
        CLKDEV_CON_ID("meram0", &mstp_clks[HWBLK_MERAM]),
@@ -324,6 +261,19 @@ static struct clk_lookup lookups[] = {
        CLKDEV_CON_ID("veu0", &mstp_clks[HWBLK_VEU2H0]),
        CLKDEV_CON_ID("vpu0", &mstp_clks[HWBLK_VPU]),
        CLKDEV_CON_ID("lcdc0", &mstp_clks[HWBLK_LCDC]),
+
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.0", &mstp_clks[HWBLK_TMU0]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.1", &mstp_clks[HWBLK_TMU0]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.2", &mstp_clks[HWBLK_TMU0]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.3", &mstp_clks[HWBLK_TMU1]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.4", &mstp_clks[HWBLK_TMU1]),
+       CLKDEV_ICK_ID("tmu_fck", "sh_tmu.5", &mstp_clks[HWBLK_TMU1]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[HWBLK_SCIF0]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.1", &mstp_clks[HWBLK_SCIF1]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.2", &mstp_clks[HWBLK_SCIF2]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.3", &mstp_clks[HWBLK_SCIF3]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.4", &mstp_clks[HWBLK_SCIF4]),
+       CLKDEV_ICK_ID("sci_fck", "sh-sci.5", &mstp_clks[HWBLK_SCIF5]),
 };
 
 int __init arch_clk_init(void)
index 8668f557e0aca654d72a049eeb3b0016202be3bf..9ee4b3667ddfe9218b657d5f94fc9a01ca04925b 100644 (file)
@@ -111,13 +111,16 @@ static struct clk div3_clk = {
        .parent         = &pll_clk,
 };
 
-/* External input clock (pin name: FSIMCKA/FSIMCKB ) */
+/* External input clock (pin name: FSIMCKA/FSIMCKB/DV_CLKI ) */
 struct clk sh7724_fsimcka_clk = {
 };
 
 struct clk sh7724_fsimckb_clk = {
 };
 
+struct clk sh7724_dv_clki = {
+};
+
 static struct clk *main_clks[] = {
        &r_clk,
        &extal_clk,
@@ -126,6 +129,7 @@ static struct clk *main_clks[] = {
        &div3_clk,
        &sh7724_fsimcka_clk,
        &sh7724_fsimckb_clk,
+       &sh7724_dv_clki,
 };
 
 static void div4_kick(struct clk *clk)
@@ -163,17 +167,20 @@ struct clk div4_clks[DIV4_NR] = {
        [DIV4_M1] = DIV4(FRQCRB, 4, 0x2f7c, CLK_ENABLE_ON_INIT),
 };
 
-enum { DIV6_V, DIV6_I, DIV6_S, DIV6_NR };
+enum { DIV6_V, DIV6_I, DIV6_S, DIV6_FA, DIV6_FB, DIV6_NR };
 
-static struct clk div6_clks[DIV6_NR] = {
-       [DIV6_V] = SH_CLK_DIV6(&div3_clk, VCLKCR, 0),
-       [DIV6_I] = SH_CLK_DIV6(&div3_clk, IRDACLKCR, 0),
-       [DIV6_S] = SH_CLK_DIV6(&div3_clk, SPUCLKCR, CLK_ENABLE_ON_INIT),
+/* Indices are important - they are the actual src selecting values */
+static struct clk *common_parent[] = {
+       [0] = &div3_clk,
+       [1] = NULL,
 };
 
-enum { DIV6_FA, DIV6_FB, DIV6_REPARENT_NR };
+static struct clk *vclkcr_parent[8] = {
+       [0] = &div3_clk,
+       [2] = &sh7724_dv_clki,
+       [4] = &extal_clk,
+};
 
-/* Indices are important - they are the actual src selecting values */
 static struct clk *fclkacr_parent[] = {
        [0] = &div3_clk,
        [1] = NULL,
@@ -188,10 +195,16 @@ static struct clk *fclkbcr_parent[] = {
        [3] = NULL,
 };
 
-static struct clk div6_reparent_clks[DIV6_REPARENT_NR] = {
-       [DIV6_FA] = SH_CLK_DIV6_EXT(&div3_clk, FCLKACR, 0,
+static struct clk div6_clks[DIV6_NR] = {
+       [DIV6_V] = SH_CLK_DIV6_EXT(VCLKCR, 0,
+                       vclkcr_parent, ARRAY_SIZE(vclkcr_parent), 12, 3),
+       [DIV6_I] = SH_CLK_DIV6_EXT(IRDACLKCR, 0,
+                       common_parent, ARRAY_SIZE(common_parent), 6, 1),
+       [DIV6_S] = SH_CLK_DIV6_EXT(SPUCLKCR, CLK_ENABLE_ON_INIT,
+                       common_parent, ARRAY_SIZE(common_parent), 6, 1),
+       [DIV6_FA] = SH_CLK_DIV6_EXT(FCLKACR, 0,
                                      fclkacr_parent, ARRAY_SIZE(fclkacr_parent), 6, 2),
-       [DIV6_FB] = SH_CLK_DIV6_EXT(&div3_clk, FCLKBCR, 0,
+       [DIV6_FB] = SH_CLK_DIV6_EXT(FCLKBCR, 0,
                                      fclkbcr_parent, ARRAY_SIZE(fclkbcr_parent), 6, 2),
 };
 
@@ -269,8 +282,8 @@ static struct clk_lookup lookups[] = {
 
        /* DIV6 clocks */
        CLKDEV_CON_ID("video_clk", &div6_clks[DIV6_V]),
-       CLKDEV_CON_ID("fsia_clk", &div6_reparent_clks[DIV6_FA]),
-       CLKDEV_CON_ID("fsib_clk", &div6_reparent_clks[DIV6_FB]),
+       CLKDEV_CON_ID("fsia_clk", &div6_clks[DIV6_FA]),
+       CLKDEV_CON_ID("fsib_clk", &div6_clks[DIV6_FB]),
        CLKDEV_CON_ID("irda_clk", &div6_clks[DIV6_I]),
        CLKDEV_CON_ID("spu_clk", &div6_clks[DIV6_S]),
 
@@ -356,10 +369,7 @@ int __init arch_clk_init(void)
                ret = sh_clk_div4_register(div4_clks, DIV4_NR, &div4_table);
 
        if (!ret)
-               ret = sh_clk_div6_register(div6_clks, DIV6_NR);
-
-       if (!ret)
-               ret = sh_clk_div6_reparent_register(div6_reparent_clks, DIV6_REPARENT_NR);
+               ret = sh_clk_div6_reparent_register(div6_clks, DIV6_NR);
 
        if (!ret)
                ret = sh_hwblk_clk_register(mstp_clks, HWBLK_NR);
index 19222dae8233ab7d8c3b754eca4d48af3aff6914..0fbff1422f5454c239a54bb77a182b30fc696a6c 100644 (file)
@@ -129,7 +129,7 @@ static struct clk_lookup lookups[] = {
        CLKDEV_ICK_ID("sci_fck", "sh-sci.0", &mstp_clks[MSTP110]),
 
        CLKDEV_CON_ID("usb_fck", &mstp_clks[MSTP103]),
-       CLKDEV_CON_ID("usb0", &mstp_clks[MSTP102]),
+       CLKDEV_DEV_ID("renesas_usbhs.0", &mstp_clks[MSTP102]),
        CLKDEV_CON_ID("mmc0", &mstp_clks[MSTP220]),
 };
 
index db257a35e71a545aa724b97d40dbdd6dbf1fe7f2..7715de2629c104de4e98a87836ea2ef308a743c4 100644 (file)
@@ -355,7 +355,7 @@ static int clk_establish_mapping(struct clk *clk)
                 */
                if (!clk->parent) {
                        clk->mapping = &dummy_mapping;
-                       return 0;
+                       goto out;
                }
 
                /*
@@ -384,6 +384,9 @@ static int clk_establish_mapping(struct clk *clk)
        }
 
        clk->mapping = mapping;
+out:
+       clk->mapped_reg = clk->mapping->base;
+       clk->mapped_reg += (phys_addr_t)clk->enable_reg - clk->mapping->phys;
        return 0;
 }
 
@@ -402,10 +405,12 @@ static void clk_teardown_mapping(struct clk *clk)
 
        /* Nothing to do */
        if (mapping == &dummy_mapping)
-               return;
+               goto out;
 
        kref_put(&mapping->ref, clk_destroy_mapping);
        clk->mapping = NULL;
+out:
+       clk->mapped_reg = NULL;
 }
 
 int clk_register(struct clk *clk)
index 82dd6fb178386a31ef29ee4adc1dcd96ccf221c5..45fee368b0925bec46312dbbe7569c8b5ca2dfc2 100644 (file)
 
 static int sh_clk_mstp32_enable(struct clk *clk)
 {
-       __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << clk->enable_bit),
-                    clk->enable_reg);
+       iowrite32(ioread32(clk->mapped_reg) & ~(1 << clk->enable_bit),
+                 clk->mapped_reg);
        return 0;
 }
 
 static void sh_clk_mstp32_disable(struct clk *clk)
 {
-       __raw_writel(__raw_readl(clk->enable_reg) | (1 << clk->enable_bit),
-                    clk->enable_reg);
+       iowrite32(ioread32(clk->mapped_reg) | (1 << clk->enable_bit),
+                 clk->mapped_reg);
 }
 
 static struct clk_ops sh_clk_mstp32_clk_ops = {
@@ -72,7 +72,7 @@ static unsigned long sh_clk_div6_recalc(struct clk *clk)
        clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
                             table, NULL);
 
-       idx = __raw_readl(clk->enable_reg) & 0x003f;
+       idx = ioread32(clk->mapped_reg) & 0x003f;
 
        return clk->freq_table[idx].frequency;
 }
@@ -98,10 +98,10 @@ static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
        if (ret < 0)
                return ret;
 
-       value = __raw_readl(clk->enable_reg) &
+       value = ioread32(clk->mapped_reg) &
                ~(((1 << clk->src_width) - 1) << clk->src_shift);
 
-       __raw_writel(value | (i << clk->src_shift), clk->enable_reg);
+       iowrite32(value | (i << clk->src_shift), clk->mapped_reg);
 
        /* Rebuild the frequency table */
        clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
@@ -119,10 +119,10 @@ static int sh_clk_div6_set_rate(struct clk *clk, unsigned long rate)
        if (idx < 0)
                return idx;
 
-       value = __raw_readl(clk->enable_reg);
+       value = ioread32(clk->mapped_reg);
        value &= ~0x3f;
        value |= idx;
-       __raw_writel(value, clk->enable_reg);
+       iowrite32(value, clk->mapped_reg);
        return 0;
 }
 
@@ -133,9 +133,9 @@ static int sh_clk_div6_enable(struct clk *clk)
 
        ret = sh_clk_div6_set_rate(clk, clk->rate);
        if (ret == 0) {
-               value = __raw_readl(clk->enable_reg);
+               value = ioread32(clk->mapped_reg);
                value &= ~0x100; /* clear stop bit to enable clock */
-               __raw_writel(value, clk->enable_reg);
+               iowrite32(value, clk->mapped_reg);
        }
        return ret;
 }
@@ -144,10 +144,10 @@ static void sh_clk_div6_disable(struct clk *clk)
 {
        unsigned long value;
 
-       value = __raw_readl(clk->enable_reg);
+       value = ioread32(clk->mapped_reg);
        value |= 0x100; /* stop clock */
        value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */
-       __raw_writel(value, clk->enable_reg);
+       iowrite32(value, clk->mapped_reg);
 }
 
 static struct clk_ops sh_clk_div6_clk_ops = {
@@ -167,6 +167,38 @@ static struct clk_ops sh_clk_div6_reparent_clk_ops = {
        .set_parent     = sh_clk_div6_set_parent,
 };
 
+static int __init sh_clk_init_parent(struct clk *clk)
+{
+       u32 val;
+
+       if (clk->parent)
+               return 0;
+
+       if (!clk->parent_table || !clk->parent_num)
+               return 0;
+
+       if (!clk->src_width) {
+               pr_err("sh_clk_init_parent: cannot select parent clock\n");
+               return -EINVAL;
+       }
+
+       val  = (ioread32(clk->mapped_reg) >> clk->src_shift);
+       val &= (1 << clk->src_width) - 1;
+
+       if (val >= clk->parent_num) {
+               pr_err("sh_clk_init_parent: parent table size failed\n");
+               return -EINVAL;
+       }
+
+       clk->parent = clk->parent_table[val];
+       if (!clk->parent) {
+               pr_err("sh_clk_init_parent: unable to set parent");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 static int __init sh_clk_div6_register_ops(struct clk *clks, int nr,
                                           struct clk_ops *ops)
 {
@@ -190,8 +222,11 @@ static int __init sh_clk_div6_register_ops(struct clk *clks, int nr,
                clkp->ops = ops;
                clkp->freq_table = freq_table + (k * freq_table_size);
                clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
-
                ret = clk_register(clkp);
+               if (ret < 0)
+                       break;
+
+               ret = sh_clk_init_parent(clkp);
        }
 
        return ret;
@@ -217,7 +252,7 @@ static unsigned long sh_clk_div4_recalc(struct clk *clk)
        clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
                             table, &clk->arch_flags);
 
-       idx = (__raw_readl(clk->enable_reg) >> clk->enable_bit) & 0x000f;
+       idx = (ioread32(clk->mapped_reg) >> clk->enable_bit) & 0x000f;
 
        return clk->freq_table[idx].frequency;
 }
@@ -235,15 +270,15 @@ static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
         */
 
        if (parent->flags & CLK_ENABLE_ON_INIT)
-               value = __raw_readl(clk->enable_reg) & ~(1 << 7);
+               value = ioread32(clk->mapped_reg) & ~(1 << 7);
        else
-               value = __raw_readl(clk->enable_reg) | (1 << 7);
+               value = ioread32(clk->mapped_reg) | (1 << 7);
 
        ret = clk_reparent(clk, parent);
        if (ret < 0)
                return ret;
 
-       __raw_writel(value, clk->enable_reg);
+       iowrite32(value, clk->mapped_reg);
 
        /* Rebiuld the frequency table */
        clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
@@ -260,10 +295,10 @@ static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate)
        if (idx < 0)
                return idx;
 
-       value = __raw_readl(clk->enable_reg);
+       value = ioread32(clk->mapped_reg);
        value &= ~(0xf << clk->enable_bit);
        value |= (idx << clk->enable_bit);
-       __raw_writel(value, clk->enable_reg);
+       iowrite32(value, clk->mapped_reg);
 
        if (d4t->kick)
                d4t->kick(clk);
@@ -273,13 +308,13 @@ static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate)
 
 static int sh_clk_div4_enable(struct clk *clk)
 {
-       __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << 8), clk->enable_reg);
+       iowrite32(ioread32(clk->mapped_reg) & ~(1 << 8), clk->mapped_reg);
        return 0;
 }
 
 static void sh_clk_div4_disable(struct clk *clk)
 {
-       __raw_writel(__raw_readl(clk->enable_reg) | (1 << 8), clk->enable_reg);
+       iowrite32(ioread32(clk->mapped_reg) | (1 << 8), clk->mapped_reg);
 }
 
 static struct clk_ops sh_clk_div4_clk_ops = {
index e67fe170d8d5e8bef9c7683f6490bf1a7be9dbc6..e7d127a9c1c54ad619fba61fd1fd98953e594f6d 100644 (file)
 #include <linux/irq.h>
 #include <linux/bitops.h>
 #include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+
+static void pfc_iounmap(struct pinmux_info *pip)
+{
+       int k;
+
+       for (k = 0; k < pip->num_resources; k++)
+               if (pip->window[k].virt)
+                       iounmap(pip->window[k].virt);
+
+       kfree(pip->window);
+       pip->window = NULL;
+}
+
+static int pfc_ioremap(struct pinmux_info *pip)
+{
+       struct resource *res;
+       int k;
+
+       if (!pip->num_resources)
+               return 0;
+
+       pip->window = kzalloc(pip->num_resources * sizeof(*pip->window),
+                             GFP_NOWAIT);
+       if (!pip->window)
+               goto err1;
+
+       for (k = 0; k < pip->num_resources; k++) {
+               res = pip->resource + k;
+               WARN_ON(resource_type(res) != IORESOURCE_MEM);
+               pip->window[k].phys = res->start;
+               pip->window[k].size = resource_size(res);
+               pip->window[k].virt = ioremap_nocache(res->start,
+                                                        resource_size(res));
+               if (!pip->window[k].virt)
+                       goto err2;
+       }
+
+       return 0;
+
+err2:
+       pfc_iounmap(pip);
+err1:
+       return -1;
+}
+
+static void __iomem *pfc_phys_to_virt(struct pinmux_info *pip,
+                                     unsigned long address)
+{
+       struct pfc_window *window;
+       int k;
+
+       /* scan through physical windows and convert address */
+       for (k = 0; k < pip->num_resources; k++) {
+               window = pip->window + k;
+
+               if (address < window->phys)
+                       continue;
+
+               if (address >= (window->phys + window->size))
+                       continue;
+
+               return window->virt + (address - window->phys);
+       }
+
+       /* no windows defined, register must be 1:1 mapped virt:phys */
+       return (void __iomem *)address;
+}
 
 static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r)
 {
@@ -31,35 +100,35 @@ static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r)
        return 1;
 }
 
-static unsigned long gpio_read_raw_reg(unsigned long reg,
+static unsigned long gpio_read_raw_reg(void __iomem *mapped_reg,
                                       unsigned long reg_width)
 {
        switch (reg_width) {
        case 8:
-               return __raw_readb(reg);
+               return ioread8(mapped_reg);
        case 16:
-               return __raw_readw(reg);
+               return ioread16(mapped_reg);
        case 32:
-               return __raw_readl(reg);
+               return ioread32(mapped_reg);
        }
 
        BUG();
        return 0;
 }
 
-static void gpio_write_raw_reg(unsigned long reg,
+static void gpio_write_raw_reg(void __iomem *mapped_reg,
                               unsigned long reg_width,
                               unsigned long data)
 {
        switch (reg_width) {
        case 8:
-               __raw_writeb(data, reg);
+               iowrite8(data, mapped_reg);
                return;
        case 16:
-               __raw_writew(data, reg);
+               iowrite16(data, mapped_reg);
                return;
        case 32:
-               __raw_writel(data, reg);
+               iowrite32(data, mapped_reg);
                return;
        }
 
@@ -82,11 +151,12 @@ static void gpio_write_bit(struct pinmux_data_reg *dr,
        else
                clear_bit(pos, &dr->reg_shadow);
 
-       gpio_write_raw_reg(dr->reg, dr->reg_width, dr->reg_shadow);
+       gpio_write_raw_reg(dr->mapped_reg, dr->reg_width, dr->reg_shadow);
 }
 
-static int gpio_read_reg(unsigned long reg, unsigned long reg_width,
-                        unsigned long field_width, unsigned long in_pos)
+static int gpio_read_reg(void __iomem *mapped_reg, unsigned long reg_width,
+                        unsigned long field_width, unsigned long in_pos,
+                        unsigned long reg)
 {
        unsigned long data, mask, pos;
 
@@ -98,13 +168,13 @@ static int gpio_read_reg(unsigned long reg, unsigned long reg_width,
                 "r_width = %ld, f_width = %ld\n",
                 reg, pos, reg_width, field_width);
 
-       data = gpio_read_raw_reg(reg, reg_width);
+       data = gpio_read_raw_reg(mapped_reg, reg_width);
        return (data >> pos) & mask;
 }
 
-static void gpio_write_reg(unsigned long reg, unsigned long reg_width,
+static void gpio_write_reg(void __iomem *mapped_reg, unsigned long reg_width,
                           unsigned long field_width, unsigned long in_pos,
-                          unsigned long value)
+                          unsigned long value, unsigned long reg)
 {
        unsigned long mask, pos;
 
@@ -120,13 +190,13 @@ static void gpio_write_reg(unsigned long reg, unsigned long reg_width,
 
        switch (reg_width) {
        case 8:
-               __raw_writeb((__raw_readb(reg) & mask) | value, reg);
+               iowrite8((ioread8(mapped_reg) & mask) | value, mapped_reg);
                break;
        case 16:
-               __raw_writew((__raw_readw(reg) & mask) | value, reg);
+               iowrite16((ioread16(mapped_reg) & mask) | value, mapped_reg);
                break;
        case 32:
-               __raw_writel((__raw_readl(reg) & mask) | value, reg);
+               iowrite32((ioread32(mapped_reg) & mask) | value, mapped_reg);
                break;
        }
 }
@@ -147,6 +217,8 @@ static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio)
                if (!data_reg->reg_width)
                        break;
 
+               data_reg->mapped_reg = pfc_phys_to_virt(gpioc, data_reg->reg);
+
                for (n = 0; n < data_reg->reg_width; n++) {
                        if (data_reg->enum_ids[n] == gpiop->enum_id) {
                                gpiop->flags &= ~PINMUX_FLAG_DREG;
@@ -179,7 +251,8 @@ static void setup_data_regs(struct pinmux_info *gpioc)
                if (!drp->reg_width)
                        break;
 
-               drp->reg_shadow = gpio_read_raw_reg(drp->reg, drp->reg_width);
+               drp->reg_shadow = gpio_read_raw_reg(drp->mapped_reg,
+                                                   drp->reg_width);
                k++;
        }
 }
@@ -266,12 +339,16 @@ static void write_config_reg(struct pinmux_info *gpioc,
                             int index)
 {
        unsigned long ncomb, pos, value;
+       void __iomem *mapped_reg;
 
        ncomb = 1 << crp->field_width;
        pos = index / ncomb;
        value = index % ncomb;
 
-       gpio_write_reg(crp->reg, crp->reg_width, crp->field_width, pos, value);
+       mapped_reg = pfc_phys_to_virt(gpioc, crp->reg);
+
+       gpio_write_reg(mapped_reg, crp->reg_width, crp->field_width,
+                      pos, value, crp->reg);
 }
 
 static int check_config_reg(struct pinmux_info *gpioc,
@@ -279,13 +356,16 @@ static int check_config_reg(struct pinmux_info *gpioc,
                            int index)
 {
        unsigned long ncomb, pos, value;
+       void __iomem *mapped_reg;
 
        ncomb = 1 << crp->field_width;
        pos = index / ncomb;
        value = index % ncomb;
 
-       if (gpio_read_reg(crp->reg, crp->reg_width,
-                         crp->field_width, pos) == value)
+       mapped_reg = pfc_phys_to_virt(gpioc, crp->reg);
+
+       if (gpio_read_reg(mapped_reg, crp->reg_width,
+                         crp->field_width, pos, crp->reg) == value)
                return 0;
 
        return -1;
@@ -564,7 +644,7 @@ static int sh_gpio_get_value(struct pinmux_info *gpioc, unsigned gpio)
        if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0)
                return -EINVAL;
 
-       return gpio_read_reg(dr->reg, dr->reg_width, 1, bit);
+       return gpio_read_reg(dr->mapped_reg, dr->reg_width, 1, bit, dr->reg);
 }
 
 static int sh_gpio_get(struct gpio_chip *chip, unsigned offset)
@@ -606,10 +686,15 @@ static int sh_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
 int register_pinmux(struct pinmux_info *pip)
 {
        struct gpio_chip *chip = &pip->chip;
+       int ret;
 
        pr_info("%s handling gpio %d -> %d\n",
                pip->name, pip->first_gpio, pip->last_gpio);
 
+       ret = pfc_ioremap(pip);
+       if (ret < 0)
+               return ret;
+
        setup_data_regs(pip);
 
        chip->request = sh_gpio_request;
@@ -627,12 +712,16 @@ int register_pinmux(struct pinmux_info *pip)
        chip->base = pip->first_gpio;
        chip->ngpio = (pip->last_gpio - pip->first_gpio) + 1;
 
-       return gpiochip_add(chip);
+       ret = gpiochip_add(chip);
+       if (ret < 0)
+               pfc_iounmap(pip);
+
+       return ret;
 }
 
 int unregister_pinmux(struct pinmux_info *pip)
 {
        pr_info("%s deregistering\n", pip->name);
-
+       pfc_iounmap(pip);
        return gpiochip_remove(&pip->chip);
 }
index aff9d612dff02a46b38d6b4133d0283dbc3f8468..9e62349b3d9f22cfeb59d2fcea49da4b068aac34 100644 (file)
@@ -50,6 +50,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/scatterlist.h>
 #include <linux/slab.h>
+#include <linux/gpio.h>
 
 #ifdef CONFIG_SUPERH
 #include <asm/sh_bios.h>
@@ -73,6 +74,7 @@ struct sci_port {
        struct clk              *fclk;
 
        char                    *irqstr[SCIx_NR_IRQS];
+       char                    *gpiostr[SCIx_NR_FNS];
 
        struct dma_chan                 *chan_tx;
        struct dma_chan                 *chan_rx;
@@ -474,8 +476,15 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag)
        if (!reg->size)
                return;
 
-       if (!(cflag & CRTSCTS))
-               sci_out(port, SCSPTR, 0x0080); /* Set RTS = 1 */
+       if ((s->cfg->capabilities & SCIx_HAVE_RTSCTS) &&
+           ((!(cflag & CRTSCTS)))) {
+               unsigned short status;
+
+               status = sci_in(port, SCSPTR);
+               status &= ~SCSPTR_CTSIO;
+               status |= SCSPTR_RTSIO;
+               sci_out(port, SCSPTR, status); /* Set RTS = 1 */
+       }
 }
 
 static int sci_txfill(struct uart_port *port)
@@ -621,6 +630,7 @@ static void sci_receive_chars(struct uart_port *port)
                } else {
                        for (i = 0; i < count; i++) {
                                char c = sci_in(port, SCxRDR);
+
                                status = sci_in(port, SCxSR);
 #if defined(CONFIG_CPU_SH3)
                                /* Skip "chars" during break */
@@ -649,9 +659,11 @@ static void sci_receive_chars(struct uart_port *port)
                                /* Store data and status */
                                if (status & SCxSR_FER(port)) {
                                        flag = TTY_FRAME;
+                                       port->icount.frame++;
                                        dev_notice(port->dev, "frame error\n");
                                } else if (status & SCxSR_PER(port)) {
                                        flag = TTY_PARITY;
+                                       port->icount.parity++;
                                        dev_notice(port->dev, "parity error\n");
                                } else
                                        flag = TTY_NORMAL;
@@ -723,6 +735,8 @@ static int sci_handle_errors(struct uart_port *port)
         */
        if (s->cfg->overrun_bit != SCIx_NOT_SUPPORTED) {
                if (status & (1 << s->cfg->overrun_bit)) {
+                       port->icount.overrun++;
+
                        /* overrun error */
                        if (tty_insert_flip_char(tty, 0, TTY_OVERRUN))
                                copied++;
@@ -737,6 +751,8 @@ static int sci_handle_errors(struct uart_port *port)
                        struct sci_port *sci_port = to_sci_port(port);
 
                        if (!sci_port->break_flag) {
+                               port->icount.brk++;
+
                                sci_port->break_flag = 1;
                                sci_schedule_break_timer(sci_port);
 
@@ -752,6 +768,8 @@ static int sci_handle_errors(struct uart_port *port)
 
                } else {
                        /* frame error */
+                       port->icount.frame++;
+
                        if (tty_insert_flip_char(tty, 0, TTY_FRAME))
                                copied++;
 
@@ -761,6 +779,8 @@ static int sci_handle_errors(struct uart_port *port)
 
        if (status & SCxSR_PER(port)) {
                /* parity error */
+               port->icount.parity++;
+
                if (tty_insert_flip_char(tty, 0, TTY_PARITY))
                        copied++;
 
@@ -787,6 +807,8 @@ static int sci_handle_fifo_overrun(struct uart_port *port)
        if ((sci_in(port, SCLSR) & (1 << s->cfg->overrun_bit))) {
                sci_out(port, SCLSR, 0);
 
+               port->icount.overrun++;
+
                tty_insert_flip_char(tty, 0, TTY_OVERRUN);
                tty_flip_buffer_push(tty);
 
@@ -812,6 +834,9 @@ static int sci_handle_breaks(struct uart_port *port)
                /* Debounce break */
                s->break_flag = 1;
 #endif
+
+               port->icount.brk++;
+
                /* Notify of BREAK */
                if (tty_insert_flip_char(tty, 0, TTY_BREAK))
                        copied++;
@@ -1082,6 +1107,67 @@ static void sci_free_irq(struct sci_port *port)
        }
 }
 
+static const char *sci_gpio_names[SCIx_NR_FNS] = {
+       "sck", "rxd", "txd", "cts", "rts",
+};
+
+static const char *sci_gpio_str(unsigned int index)
+{
+       return sci_gpio_names[index];
+}
+
+static void __devinit sci_init_gpios(struct sci_port *port)
+{
+       struct uart_port *up = &port->port;
+       int i;
+
+       if (!port->cfg)
+               return;
+
+       for (i = 0; i < SCIx_NR_FNS; i++) {
+               const char *desc;
+               int ret;
+
+               if (!port->cfg->gpios[i])
+                       continue;
+
+               desc = sci_gpio_str(i);
+
+               port->gpiostr[i] = kasprintf(GFP_KERNEL, "%s:%s",
+                                            dev_name(up->dev), desc);
+
+               /*
+                * If we've failed the allocation, we can still continue
+                * on with a NULL string.
+                */
+               if (!port->gpiostr[i])
+                       dev_notice(up->dev, "%s string allocation failure\n",
+                                  desc);
+
+               ret = gpio_request(port->cfg->gpios[i], port->gpiostr[i]);
+               if (unlikely(ret != 0)) {
+                       dev_notice(up->dev, "failed %s gpio request\n", desc);
+
+                       /*
+                        * If we can't get the GPIO for whatever reason,
+                        * no point in keeping the verbose string around.
+                        */
+                       kfree(port->gpiostr[i]);
+               }
+       }
+}
+
+static void sci_free_gpios(struct sci_port *port)
+{
+       int i;
+
+       for (i = 0; i < SCIx_NR_FNS; i++)
+               if (port->cfg->gpios[i]) {
+                       gpio_free(port->cfg->gpios[i]);
+                       kfree(port->gpiostr[i]);
+               }
+}
+
 static unsigned int sci_tx_empty(struct uart_port *port)
 {
        unsigned short status = sci_in(port, SCxSR);
@@ -1090,19 +1176,39 @@ static unsigned int sci_tx_empty(struct uart_port *port)
        return (status & SCxSR_TEND(port)) && !in_tx_fifo ? TIOCSER_TEMT : 0;
 }
 
+/*
+ * Modem control is a bit of a mixed bag for SCI(F) ports. Generally
+ * CTS/RTS is supported in hardware by at least one port and controlled
+ * via SCSPTR (SCxPCR for SCIFA/B parts), or external pins (presently
+ * handled via the ->init_pins() op, which is a bit of a one-way street,
+ * lacking any ability to defer pin control -- this will later be
+ * converted over to the GPIO framework).
+ *
+ * Other modes (such as loopback) are supported generically on certain
+ * port types, but not others. For these it's sufficient to test for the
+ * existence of the support register and simply ignore the port type.
+ */
 static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
-       /* This routine is used for seting signals of: DTR, DCD, CTS/RTS */
-       /* We use SCIF's hardware for CTS/RTS, so don't need any for that. */
-       /* If you have signals for DTR and DCD, please implement here. */
+       if (mctrl & TIOCM_LOOP) {
+               struct plat_sci_reg *reg;
+
+               /*
+                * Standard loopback mode for SCFCR ports.
+                */
+               reg = sci_getreg(port, SCFCR);
+               if (reg->size)
+                       sci_out(port, SCFCR, sci_in(port, SCFCR) | 1);
+       }
 }
 
 static unsigned int sci_get_mctrl(struct uart_port *port)
 {
-       /* This routine is used for getting signals of: DTR, DCD, DSR, RI,
-          and CTS/RTS */
-
-       return TIOCM_DTR | TIOCM_RTS | TIOCM_CTS | TIOCM_DSR;
+       /*
+        * CTS/RTS is handled in hardware when supported, while nothing
+        * else is wired up. Keep it simple and simply assert DSR/CAR.
+        */
+       return TIOCM_DSR | TIOCM_CAR;
 }
 
 #ifdef CONFIG_SERIAL_SH_SCI_DMA
@@ -1449,12 +1555,17 @@ static void sci_stop_rx(struct uart_port *port)
 
 static void sci_enable_ms(struct uart_port *port)
 {
-       /* Nothing here yet .. */
+       /*
+        * Not supported by hardware, always a nop.
+        */
 }
 
 static void sci_break_ctl(struct uart_port *port, int break_state)
 {
-       /* Nothing here yet .. */
+       /*
+        * Not supported by hardware. Most parts couple break and rx
+        * interrupts together, with break detection always enabled.
+        */
 }
 
 #ifdef CONFIG_SERIAL_SH_SCI_DMA
@@ -1652,6 +1763,7 @@ static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps,
 
 static void sci_reset(struct uart_port *port)
 {
+       struct plat_sci_reg *reg;
        unsigned int status;
 
        do {
@@ -1660,7 +1772,8 @@ static void sci_reset(struct uart_port *port)
 
        sci_out(port, SCSCR, 0x00);     /* TE=0, RE=0, CKE1=0 */
 
-       if (port->type != PORT_SCI)
+       reg = sci_getreg(port, SCFCR);
+       if (reg->size)
                sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST);
 }
 
@@ -1668,9 +1781,9 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
                            struct ktermios *old)
 {
        struct sci_port *s = to_sci_port(port);
+       struct plat_sci_reg *reg;
        unsigned int baud, smr_val, max_baud;
        int t = -1;
-       u16 scfcr = 0;
 
        /*
         * earlyprintk comes here early on with port->uartclk set to zero.
@@ -1720,7 +1833,27 @@ 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));
+
+       reg = sci_getreg(port, SCFCR);
+       if (reg->size) {
+               unsigned short ctrl = sci_in(port, SCFCR);
+
+               if (s->cfg->capabilities & SCIx_HAVE_RTSCTS) {
+                       if (termios->c_cflag & CRTSCTS)
+                               ctrl |= SCFCR_MCE;
+                       else
+                               ctrl &= ~SCFCR_MCE;
+               }
+
+               /*
+                * As we've done a sci_reset() above, ensure we don't
+                * interfere with the FIFOs while toggling MCE. As the
+                * reset values could still be set, simply mask them out.
+                */
+               ctrl &= ~(SCFCR_RFRST | SCFCR_TFRST);
+
+               sci_out(port, SCFCR, ctrl);
+       }
 
        sci_out(port, SCSCR, s->cfg->scscr);
 
@@ -1892,6 +2025,8 @@ static int __devinit sci_init_single(struct platform_device *dev,
        struct uart_port *port = &sci_port->port;
        int ret;
 
+       sci_port->cfg   = p;
+
        port->ops       = &sci_uart_ops;
        port->iotype    = UPIO_MEM;
        port->line      = index;
@@ -1937,6 +2072,8 @@ static int __devinit sci_init_single(struct platform_device *dev,
 
                port->dev = &dev->dev;
 
+               sci_init_gpios(sci_port);
+
                pm_runtime_irq_safe(&dev->dev);
                pm_runtime_enable(&dev->dev);
        }
@@ -1971,8 +2108,6 @@ static int __devinit sci_init_single(struct platform_device *dev,
                p->error_mask |= (1 << p->overrun_bit);
        }
 
-       sci_port->cfg           = p;
-
        port->mapbase           = p->mapbase;
        port->type              = p->type;
        port->flags             = p->flags;
@@ -2113,9 +2248,16 @@ static int sci_runtime_suspend(struct device *dev)
        struct uart_port *port = &sci_port->port;
 
        if (uart_console(port)) {
+               struct plat_sci_reg *reg;
+
                sci_port->saved_smr = sci_in(port, SCSMR);
                sci_port->saved_brr = sci_in(port, SCBRR);
-               sci_port->saved_fcr = sci_in(port, SCFCR);
+
+               reg = sci_getreg(port, SCFCR);
+               if (reg->size)
+                       sci_port->saved_fcr = sci_in(port, SCFCR);
+               else
+                       sci_port->saved_fcr = 0;
        }
        return 0;
 }
@@ -2129,7 +2271,10 @@ static int sci_runtime_resume(struct device *dev)
                sci_reset(port);
                sci_out(port, SCSMR, sci_port->saved_smr);
                sci_out(port, SCBRR, sci_port->saved_brr);
-               sci_out(port, SCFCR, sci_port->saved_fcr);
+
+               if (sci_port->saved_fcr)
+                       sci_out(port, SCFCR, sci_port->saved_fcr);
+
                sci_out(port, SCSCR, sci_port->cfg->scscr);
        }
        return 0;
@@ -2169,6 +2314,8 @@ static int sci_remove(struct platform_device *dev)
        cpufreq_unregister_notifier(&port->freq_transition,
                                    CPUFREQ_TRANSITION_NOTIFIER);
 
+       sci_free_gpios(port);
+
        uart_remove_one_port(&sci_uart_driver, &port->port);
 
        clk_put(port->iclk);
index 369273a5267908791efc203537e0f349edaef0cf..78779074f6e8ff9b4f0d95fe9575e008eb0d1c81 100644 (file)
@@ -49,6 +49,10 @@ enum {
 
 #define SCIF_DEFAULT_ERROR_MASK (SCIF_PER | SCIF_FER | SCIF_ER | SCIF_BRK)
 
+/* SCSPTR, optional */
+#define SCSPTR_RTSIO   (1 << 7)
+#define SCSPTR_CTSIO   (1 << 5)
+
 /* Offsets into the sci_port->irqs array */
 enum {
        SCIx_ERI_IRQ,
@@ -60,6 +64,17 @@ enum {
        SCIx_MUX_IRQ = SCIx_NR_IRQS,    /* special case */
 };
 
+/* Offsets into the sci_port->gpios array */
+enum {
+       SCIx_SCK,
+       SCIx_RXD,
+       SCIx_TXD,
+       SCIx_CTS,
+       SCIx_RTS,
+
+       SCIx_NR_FNS,
+};
+
 enum {
        SCIx_PROBE_REGTYPE,
 
@@ -108,14 +123,21 @@ struct plat_sci_port_ops {
        void (*init_pins)(struct uart_port *, unsigned int cflag);
 };
 
+/*
+ * Port-specific capabilities
+ */
+#define SCIx_HAVE_RTSCTS       (1 << 0)
+
 /*
  * Platform device specific platform_data struct
  */
 struct plat_sci_port {
        unsigned long   mapbase;                /* resource base */
        unsigned int    irqs[SCIx_NR_IRQS];     /* ERI, RXI, TXI, BRI */
+       unsigned int    gpios[SCIx_NR_FNS];     /* SCK, RXD, TXD, CTS, RTS */
        unsigned int    type;                   /* SCI / SCIF / IRDA */
        upf_t           flags;                  /* UPF_* flags */
+       unsigned long   capabilities;           /* Port features/capabilities */
 
        unsigned int    scbrr_algo_id;          /* SCBRR calculation algo */
        unsigned int    scscr;                  /* SCSCR initialization */
index a20831cf336a5ef5f6cc427b6b131766a34ca761..54341d811685a2088897491c2255ba605b71ab43 100644 (file)
@@ -49,6 +49,7 @@ struct clk {
 
        void __iomem            *enable_reg;
        unsigned int            enable_bit;
+       void __iomem            *mapped_reg;
 
        unsigned long           arch_flags;
        void                    *priv;
@@ -131,10 +132,9 @@ int sh_clk_div4_enable_register(struct clk *clks, int nr,
 int sh_clk_div4_reparent_register(struct clk *clks, int nr,
                         struct clk_div4_table *table);
 
-#define SH_CLK_DIV6_EXT(_parent, _reg, _flags, _parents,       \
+#define SH_CLK_DIV6_EXT(_reg, _flags, _parents,                        \
                        _num_parents, _src_shift, _src_width)   \
 {                                                              \
-       .parent = _parent,                                      \
        .enable_reg = (void __iomem *)_reg,                     \
        .flags = _flags,                                        \
        .parent_table = _parents,                               \
@@ -144,7 +144,11 @@ int sh_clk_div4_reparent_register(struct clk *clks, int nr,
 }
 
 #define SH_CLK_DIV6(_parent, _reg, _flags)                     \
-       SH_CLK_DIV6_EXT(_parent, _reg, _flags, NULL, 0, 0, 0)
+{                                                              \
+       .parent         = _parent,                              \
+       .enable_reg     = (void __iomem *)_reg,                 \
+       .flags          = _flags,                               \
+}
 
 int sh_clk_div6_register(struct clk *clks, int nr);
 int sh_clk_div6_reparent_register(struct clk *clks, int nr);
index 8446789216e568008fb71e9c85189758bf0197a4..91666a58529d5a660b7bef9678cc4724466d80fc 100644 (file)
@@ -55,6 +55,7 @@ struct pinmux_cfg_reg {
 struct pinmux_data_reg {
        unsigned long reg, reg_width, reg_shadow;
        pinmux_enum_t *enum_ids;
+       void __iomem *mapped_reg;
 };
 
 #define PINMUX_DATA_REG(name, r, r_width) \
@@ -75,6 +76,12 @@ struct pinmux_range {
        pinmux_enum_t force;
 };
 
+struct pfc_window {
+       phys_addr_t phys;
+       void __iomem *virt;
+       unsigned long size;
+};
+
 struct pinmux_info {
        char *name;
        pinmux_enum_t reserved_id;
@@ -98,6 +105,10 @@ struct pinmux_info {
        struct pinmux_irq *gpio_irq;
        unsigned int gpio_irq_size;
 
+       struct resource *resource;
+       unsigned int num_resources;
+       struct pfc_window *window;
+
        struct gpio_chip chip;
 };