mirror of https://gitee.com/openkylin/linux.git
Merge branches 'common/pfc' and 'common/clkfwk' into rmobile/marzen
Conflicts: arch/arm/mach-shmobile/clock-sh73a0.c Signed-off-by: Paul Mundt <lethal@linux-sh.org>
This commit is contained in:
commit
e0a23ce20e
|
@ -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),
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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__ */
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 };
|
||||
|
||||
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),
|
||||
};
|
||||
|
||||
enum { DIV6_FA, DIV6_FB, DIV6_REPARENT_NR };
|
||||
enum { DIV6_V, DIV6_I, DIV6_S, DIV6_FA, DIV6_FB, DIV6_NR };
|
||||
|
||||
/* Indices are important - they are the actual src selecting values */
|
||||
static struct clk *common_parent[] = {
|
||||
[0] = &div3_clk,
|
||||
[1] = NULL,
|
||||
};
|
||||
|
||||
static struct clk *vclkcr_parent[8] = {
|
||||
[0] = &div3_clk,
|
||||
[2] = &sh7724_dv_clki,
|
||||
[4] = &extal_clk,
|
||||
};
|
||||
|
||||
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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -15,15 +15,15 @@
|
|||
|
||||
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,6 +222,9 @@ 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 = sh_clk_init_parent(clkp);
|
||||
if (ret < 0)
|
||||
break;
|
||||
|
||||
ret = clk_register(clkp);
|
||||
}
|
||||
|
@ -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 = {
|
||||
|
|
275
drivers/sh/pfc.c
275
drivers/sh/pfc.c
|
@ -19,6 +19,75 @@
|
|||
#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,41 +100,54 @@ 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;
|
||||
}
|
||||
|
||||
BUG();
|
||||
}
|
||||
|
||||
static int gpio_read_bit(struct pinmux_data_reg *dr,
|
||||
unsigned long in_pos)
|
||||
{
|
||||
unsigned long pos;
|
||||
|
||||
pos = dr->reg_width - (in_pos + 1);
|
||||
|
||||
pr_debug("read_bit: addr = %lx, pos = %ld, "
|
||||
"r_width = %ld\n", dr->reg, pos, dr->reg_width);
|
||||
|
||||
return (gpio_read_raw_reg(dr->mapped_reg, dr->reg_width) >> pos) & 1;
|
||||
}
|
||||
|
||||
static void gpio_write_bit(struct pinmux_data_reg *dr,
|
||||
unsigned long in_pos, unsigned long value)
|
||||
{
|
||||
|
@ -82,53 +164,72 @@ 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 void config_reg_helper(struct pinmux_info *gpioc,
|
||||
struct pinmux_cfg_reg *crp,
|
||||
unsigned long in_pos,
|
||||
void __iomem **mapped_regp,
|
||||
unsigned long *maskp,
|
||||
unsigned long *posp)
|
||||
{
|
||||
unsigned long data, mask, pos;
|
||||
int k;
|
||||
|
||||
data = 0;
|
||||
mask = (1 << field_width) - 1;
|
||||
pos = reg_width - ((in_pos + 1) * field_width);
|
||||
*mapped_regp = pfc_phys_to_virt(gpioc, crp->reg);
|
||||
|
||||
pr_debug("read_reg: addr = %lx, pos = %ld, "
|
||||
"r_width = %ld, f_width = %ld\n",
|
||||
reg, pos, reg_width, field_width);
|
||||
|
||||
data = gpio_read_raw_reg(reg, reg_width);
|
||||
return (data >> pos) & mask;
|
||||
if (crp->field_width) {
|
||||
*maskp = (1 << crp->field_width) - 1;
|
||||
*posp = crp->reg_width - ((in_pos + 1) * crp->field_width);
|
||||
} else {
|
||||
*maskp = (1 << crp->var_field_width[in_pos]) - 1;
|
||||
*posp = crp->reg_width;
|
||||
for (k = 0; k <= in_pos; k++)
|
||||
*posp -= crp->var_field_width[k];
|
||||
}
|
||||
}
|
||||
|
||||
static void gpio_write_reg(unsigned long reg, unsigned long reg_width,
|
||||
unsigned long field_width, unsigned long in_pos,
|
||||
unsigned long value)
|
||||
static int read_config_reg(struct pinmux_info *gpioc,
|
||||
struct pinmux_cfg_reg *crp,
|
||||
unsigned long field)
|
||||
{
|
||||
void __iomem *mapped_reg;
|
||||
unsigned long mask, pos;
|
||||
|
||||
mask = (1 << field_width) - 1;
|
||||
pos = reg_width - ((in_pos + 1) * field_width);
|
||||
config_reg_helper(gpioc, crp, field, &mapped_reg, &mask, &pos);
|
||||
|
||||
pr_debug("write_reg addr = %lx, value = %ld, pos = %ld, "
|
||||
pr_debug("read_reg: addr = %lx, field = %ld, "
|
||||
"r_width = %ld, f_width = %ld\n",
|
||||
reg, value, pos, reg_width, field_width);
|
||||
crp->reg, field, crp->reg_width, crp->field_width);
|
||||
|
||||
return (gpio_read_raw_reg(mapped_reg, crp->reg_width) >> pos) & mask;
|
||||
}
|
||||
|
||||
static void write_config_reg(struct pinmux_info *gpioc,
|
||||
struct pinmux_cfg_reg *crp,
|
||||
unsigned long field, unsigned long value)
|
||||
{
|
||||
void __iomem *mapped_reg;
|
||||
unsigned long mask, pos, data;
|
||||
|
||||
config_reg_helper(gpioc, crp, field, &mapped_reg, &mask, &pos);
|
||||
|
||||
pr_debug("write_reg addr = %lx, value = %ld, field = %ld, "
|
||||
"r_width = %ld, f_width = %ld\n",
|
||||
crp->reg, value, field, crp->reg_width, crp->field_width);
|
||||
|
||||
mask = ~(mask << pos);
|
||||
value = value << pos;
|
||||
|
||||
switch (reg_width) {
|
||||
case 8:
|
||||
__raw_writeb((__raw_readb(reg) & mask) | value, reg);
|
||||
break;
|
||||
case 16:
|
||||
__raw_writew((__raw_readw(reg) & mask) | value, reg);
|
||||
break;
|
||||
case 32:
|
||||
__raw_writel((__raw_readl(reg) & mask) | value, reg);
|
||||
break;
|
||||
}
|
||||
data = gpio_read_raw_reg(mapped_reg, crp->reg_width);
|
||||
data &= mask;
|
||||
data |= value;
|
||||
|
||||
if (gpioc->unlock_reg)
|
||||
gpio_write_raw_reg(pfc_phys_to_virt(gpioc, gpioc->unlock_reg),
|
||||
32, ~data);
|
||||
|
||||
gpio_write_raw_reg(mapped_reg, crp->reg_width, data);
|
||||
}
|
||||
|
||||
static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio)
|
||||
|
@ -147,6 +248,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 +282,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++;
|
||||
}
|
||||
}
|
||||
|
@ -201,12 +305,13 @@ static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio,
|
|||
}
|
||||
|
||||
static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id,
|
||||
struct pinmux_cfg_reg **crp, int *indexp,
|
||||
struct pinmux_cfg_reg **crp,
|
||||
int *fieldp, int *valuep,
|
||||
unsigned long **cntp)
|
||||
{
|
||||
struct pinmux_cfg_reg *config_reg;
|
||||
unsigned long r_width, f_width;
|
||||
int k, n;
|
||||
unsigned long r_width, f_width, curr_width, ncomb;
|
||||
int k, m, n, pos, bit_pos;
|
||||
|
||||
k = 0;
|
||||
while (1) {
|
||||
|
@ -217,13 +322,27 @@ static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id,
|
|||
|
||||
if (!r_width)
|
||||
break;
|
||||
for (n = 0; n < (r_width / f_width) * (1 << f_width); n++) {
|
||||
if (config_reg->enum_ids[n] == enum_id) {
|
||||
*crp = config_reg;
|
||||
*indexp = n;
|
||||
*cntp = &config_reg->cnt[n / (1 << f_width)];
|
||||
return 0;
|
||||
|
||||
pos = 0;
|
||||
m = 0;
|
||||
for (bit_pos = 0; bit_pos < r_width; bit_pos += curr_width) {
|
||||
if (f_width)
|
||||
curr_width = f_width;
|
||||
else
|
||||
curr_width = config_reg->var_field_width[m];
|
||||
|
||||
ncomb = 1 << curr_width;
|
||||
for (n = 0; n < ncomb; n++) {
|
||||
if (config_reg->enum_ids[pos + n] == enum_id) {
|
||||
*crp = config_reg;
|
||||
*fieldp = m;
|
||||
*valuep = n;
|
||||
*cntp = &config_reg->cnt[m];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
pos += ncomb;
|
||||
m++;
|
||||
}
|
||||
k++;
|
||||
}
|
||||
|
@ -261,36 +380,6 @@ static int get_gpio_enum_id(struct pinmux_info *gpioc, unsigned gpio,
|
|||
return -1;
|
||||
}
|
||||
|
||||
static void write_config_reg(struct pinmux_info *gpioc,
|
||||
struct pinmux_cfg_reg *crp,
|
||||
int index)
|
||||
{
|
||||
unsigned long ncomb, pos, value;
|
||||
|
||||
ncomb = 1 << crp->field_width;
|
||||
pos = index / ncomb;
|
||||
value = index % ncomb;
|
||||
|
||||
gpio_write_reg(crp->reg, crp->reg_width, crp->field_width, pos, value);
|
||||
}
|
||||
|
||||
static int check_config_reg(struct pinmux_info *gpioc,
|
||||
struct pinmux_cfg_reg *crp,
|
||||
int index)
|
||||
{
|
||||
unsigned long ncomb, pos, value;
|
||||
|
||||
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)
|
||||
return 0;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
enum { GPIO_CFG_DRYRUN, GPIO_CFG_REQ, GPIO_CFG_FREE };
|
||||
|
||||
static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
|
||||
|
@ -299,7 +388,7 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
|
|||
struct pinmux_cfg_reg *cr = NULL;
|
||||
pinmux_enum_t enum_id;
|
||||
struct pinmux_range *range;
|
||||
int in_range, pos, index;
|
||||
int in_range, pos, field, value;
|
||||
unsigned long *cntp;
|
||||
|
||||
switch (pinmux_type) {
|
||||
|
@ -330,7 +419,8 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
|
|||
|
||||
pos = 0;
|
||||
enum_id = 0;
|
||||
index = 0;
|
||||
field = 0;
|
||||
value = 0;
|
||||
while (1) {
|
||||
pos = get_gpio_enum_id(gpioc, gpio, pos, &enum_id);
|
||||
if (pos <= 0)
|
||||
|
@ -377,17 +467,19 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
|
|||
if (!in_range)
|
||||
continue;
|
||||
|
||||
if (get_config_reg(gpioc, enum_id, &cr, &index, &cntp) != 0)
|
||||
if (get_config_reg(gpioc, enum_id, &cr,
|
||||
&field, &value, &cntp) != 0)
|
||||
goto out_err;
|
||||
|
||||
switch (cfg_mode) {
|
||||
case GPIO_CFG_DRYRUN:
|
||||
if (!*cntp || !check_config_reg(gpioc, cr, index))
|
||||
if (!*cntp ||
|
||||
(read_config_reg(gpioc, cr, field) != value))
|
||||
continue;
|
||||
break;
|
||||
|
||||
case GPIO_CFG_REQ:
|
||||
write_config_reg(gpioc, cr, index);
|
||||
write_config_reg(gpioc, cr, field, value);
|
||||
*cntp = *cntp + 1;
|
||||
break;
|
||||
|
||||
|
@ -564,7 +656,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_bit(dr, bit);
|
||||
}
|
||||
|
||||
static int sh_gpio_get(struct gpio_chip *chip, unsigned offset)
|
||||
|
@ -606,10 +698,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 +724,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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -45,16 +45,24 @@ struct pinmux_cfg_reg {
|
|||
unsigned long reg, reg_width, field_width;
|
||||
unsigned long *cnt;
|
||||
pinmux_enum_t *enum_ids;
|
||||
unsigned long *var_field_width;
|
||||
};
|
||||
|
||||
#define PINMUX_CFG_REG(name, r, r_width, f_width) \
|
||||
.reg = r, .reg_width = r_width, .field_width = f_width, \
|
||||
.cnt = (unsigned long [r_width / f_width]) {}, \
|
||||
.enum_ids = (pinmux_enum_t [(r_width / f_width) * (1 << f_width)]) \
|
||||
.enum_ids = (pinmux_enum_t [(r_width / f_width) * (1 << f_width)])
|
||||
|
||||
#define PINMUX_CFG_REG_VAR(name, r, r_width, var_fw0, var_fwn...) \
|
||||
.reg = r, .reg_width = r_width, \
|
||||
.cnt = (unsigned long [r_width]) {}, \
|
||||
.var_field_width = (unsigned long [r_width]) { var_fw0, var_fwn, 0 }, \
|
||||
.enum_ids = (pinmux_enum_t [])
|
||||
|
||||
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 +83,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 +112,12 @@ struct pinmux_info {
|
|||
struct pinmux_irq *gpio_irq;
|
||||
unsigned int gpio_irq_size;
|
||||
|
||||
struct resource *resource;
|
||||
unsigned int num_resources;
|
||||
struct pfc_window *window;
|
||||
|
||||
unsigned long unlock_reg;
|
||||
|
||||
struct gpio_chip chip;
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue