void idt_init(void) { extern struct Segdesc gdt[]; // Setup a TSS so that we get the right stack // when we trap to the kernel. ts.ts_esp0 = KSTACKTOP; ts.ts_ss0 = GD_KD; // Love to put this code in the initialization of gdt, // but the compiler generates an error incorrectly. gdt[GD_TSS >> 3] = SEG16(STS_T32A, (u_long) (&ts), sizeof(struct Taskstate), 0); gdt[GD_TSS >> 3].sd_s = 0; printf("????????????????????????\n"); // Load the TSS ltr(GD_TSS); idt[0x0] = GATE(STS_IG32, GD_KT, (int)&myint0, 3); idt[0xE] = GATE(STS_IG32, GD_KT, (int)&myint14, 3); idt[0x30] = GATE(STS_IG32, GD_KT, (int)&myint30, 3); printf("????????????????????????%x\n", idt[0x30]); // Load the IDT asm volatile("lidt idt_pd+2"); }
RK2928_CLKSEL_CON(14), 8, 2, MFLAGS); static struct rockchip_clk_branch rk3228_uart2_fracmux __initdata = MUX(SCLK_UART2, "sclk_uart2", mux_uart2_p, CLK_SET_RATE_PARENT, RK2928_CLKSEL_CON(15), 8, 2, MFLAGS); static struct rockchip_clk_branch rk3228_clk_branches[] __initdata = { /* * Clock-Architecture Diagram 1 */ DIV(0, "clk_24m", "xin24m", CLK_IGNORE_UNUSED, RK2928_CLKSEL_CON(4), 8, 5, DFLAGS), /* PD_DDR */ GATE(0, "apll_ddr", "apll", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(0), 2, GFLAGS), GATE(0, "dpll_ddr", "dpll", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(0), 2, GFLAGS), GATE(0, "gpll_ddr", "gpll", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(0), 2, GFLAGS), COMPOSITE(0, "ddrphy4x", mux_ddrphy_p, CLK_IGNORE_UNUSED, RK2928_CLKSEL_CON(26), 8, 2, MFLAGS, 0, 3, DFLAGS | CLK_DIVIDER_POWER_OF_TWO, RK2928_CLKGATE_CON(7), 1, GFLAGS), GATE(0, "ddrc", "ddrphy_pre", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(8), 5, GFLAGS), FACTOR_GATE(0, "ddrphy", "ddrphy4x", CLK_IGNORE_UNUSED, 1, 4, RK2928_CLKGATE_CON(7), 0, GFLAGS), /* PD_CORE */ GATE(0, "dpll_core", "dpll", CLK_IGNORE_UNUSED, RK2928_CLKGATE_CON(0), 6, GFLAGS),
DIV(div_isp0, "div_isp0", "aclk200", E4X12_DIV_ISP0, 0, 3), DIV(div_isp1, "div_isp1", "aclk200", E4X12_DIV_ISP0, 4, 3), DIV(none, "div_mpwm", "div_isp1", E4X12_DIV_ISP1, 0, 3), DIV(div_mcuisp0, "div_mcuisp0", "aclk400_mcuisp", E4X12_DIV_ISP1, 4, 3), DIV(div_mcuisp1, "div_mcuisp1", "div_mcuisp0", E4X12_DIV_ISP1, 8, 3), DIV(sclk_fimg2d, "sclk_fimg2d", "mout_g2d", DIV_DMC1, 0, 4), }; /* list of gate clocks supported in all exynos4 soc's */ struct samsung_gate_clock exynos4_gate_clks[] __initdata = { /* * After all Exynos4 based platforms are migrated to use device tree, * the device name and clock alias names specified below for some * of the clocks can be removed. */ GATE(sclk_hdmi, "sclk_hdmi", "mout_hdmi", SRC_MASK_TV, 0, 0, 0), GATE(sclk_spdif, "sclk_spdif", "mout_spdif", SRC_MASK_PERIL1, 8, 0, 0), GATE(jpeg, "jpeg", "aclk160", GATE_IP_CAM, 6, 0, 0), GATE(mie0, "mie0", "aclk160", GATE_IP_LCD0, 1, 0, 0), GATE(dsim0, "dsim0", "aclk160", GATE_IP_LCD0, 3, 0, 0), GATE(fimd1, "fimd1", "aclk160", E4210_GATE_IP_LCD1, 0, 0, 0), GATE(mie1, "mie1", "aclk160", E4210_GATE_IP_LCD1, 1, 0, 0), GATE(dsim1, "dsim1", "aclk160", E4210_GATE_IP_LCD1, 3, 0, 0), GATE(smmu_fimd1, "smmu_fimd1", "aclk160", E4210_GATE_IP_LCD1, 4, 0, 0), GATE(tsi, "tsi", "aclk133", GATE_IP_FSYS, 4, 0, 0), GATE(sromc, "sromc", "aclk133", GATE_IP_FSYS, 11, 0, 0), GATE(sclk_g3d, "sclk_g3d", "div_g3d", GATE_IP_G3D, 0, CLK_SET_RATE_PARENT, 0), GATE(usb_device, "usb_device", "aclk133", GATE_IP_FSYS, 13, 0, 0), GATE(onenand, "onenand", "aclk133", GATE_IP_FSYS, 15, 0, 0), GATE(nfcon, "nfcon", "aclk133", GATE_IP_FSYS, 16, 0, 0),
DIV(none, "dout_i2s2", "dout_audio2", DIV_PERIC3, 12, 6), DIV(none, "dout_audio0", "mout_audio0", DIV_PERIC3, 20, 4), DIV(none, "dout_audio1", "mout_audio1", DIV_PERIC3, 24, 4), DIV(none, "dout_audio2", "mout_audio2", DIV_PERIC3, 28, 4), /* SPI Pre-Ratio */ DIV(none, "dout_pre_spi0", "dout_spi0", DIV_PERIC4, 8, 8), DIV(none, "dout_pre_spi1", "dout_spi1", DIV_PERIC4, 16, 8), DIV(none, "dout_pre_spi2", "dout_spi2", DIV_PERIC4, 24, 8), }; static struct samsung_gate_clock exynos5420_gate_clks[] __initdata = { /* TODO: Re-verify the CG bits for all the gate clocks */ GATE_A(mct, "pclk_st", "aclk66_psgen", GATE_BUS_PERIS1, 2, 0, 0, "mct"), GATE(0, "aclk200_fsys", "mout_user_aclk200_fsys", GATE_BUS_FSYS0, 9, CLK_IGNORE_UNUSED, 0), GATE(0, "aclk200_fsys2", "mout_user_aclk200_fsys2", GATE_BUS_FSYS0, 10, CLK_IGNORE_UNUSED, 0), GATE(0, "aclk333_g2d", "mout_user_aclk333_g2d", GATE_BUS_TOP, 0, CLK_IGNORE_UNUSED, 0), GATE(0, "aclk266_g2d", "mout_user_aclk266_g2d", GATE_BUS_TOP, 1, CLK_IGNORE_UNUSED, 0), GATE(0, "aclk300_jpeg", "mout_user_aclk300_jpeg", GATE_BUS_TOP, 4, CLK_IGNORE_UNUSED, 0), GATE(0, "aclk300_gscl", "mout_user_aclk300_gscl", GATE_BUS_TOP, 6, CLK_IGNORE_UNUSED, 0), GATE(0, "aclk333_432_gscl", "mout_user_aclk333_432_gscl", GATE_BUS_TOP, 7, CLK_IGNORE_UNUSED, 0), GATE(0, "pclk66_gpio", "mout_sw_aclk66", GATE_BUS_TOP, 9, CLK_IGNORE_UNUSED, 0),
static struct rockchip_clk_branch rk3368_uart4_fracmux __initdata = MUX(SCLK_UART4, "sclk_uart4", mux_uart4_p, CLK_SET_RATE_PARENT, RK3368_CLKSEL_CON(41), 8, 2, MFLAGS); static struct rockchip_clk_branch rk3368_clk_branches[] __initdata = { /* * Clock-Architecture Diagram 2 */ FACTOR(0, "xin12m", "xin24m", 0, 1, 2), MUX(SCLK_USBPHY480M, "usbphy_480m", mux_usbphy480m_p, CLK_SET_RATE_PARENT, RK3368_CLKSEL_CON(13), 8, 1, MFLAGS), GATE(0, "apllb_core", "apllb", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(0), 0, GFLAGS), GATE(0, "gpllb_core", "gpll", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(0), 1, GFLAGS), GATE(0, "aplll_core", "aplll", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(0), 4, GFLAGS), GATE(0, "gplll_core", "gpll", CLK_IGNORE_UNUSED, RK3368_CLKGATE_CON(0), 5, GFLAGS), DIV(0, "aclkm_core_b", "armclkb", 0, RK3368_CLKSEL_CON(0), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY), DIV(0, "atclk_core_b", "armclkb", 0, RK3368_CLKSEL_CON(1), 0, 5, DFLAGS | CLK_DIVIDER_READ_ONLY), DIV(0, "pclk_dbg_b", "armclkb", 0, RK3368_CLKSEL_CON(1), 8, 5, DFLAGS | CLK_DIVIDER_READ_ONLY),
DIV(DOUT_DPM, "dout_dpm", "dout_pclkp", CLK_DIV7, 8, 7), DIV(DOUT_DVSEM, "dout_dvsem", "dout_pclkp", CLK_DIV7, 0, 7), }; /* S5P6442-specific clock dividers. */ static struct samsung_div_clock s5p6442_div_clks[] __initdata = { DIV(DOUT_HCLKP, "dout_hclkp", "mout_d1sync", CLK_DIV0, 24, 4), DIV(DOUT_HCLKD, "dout_hclkd", "mout_d0sync", CLK_DIV0, 16, 4), DIV(DOUT_MIXER, "dout_mixer", "mout_vpll", CLK_DIV1, 0, 4), }; /* Common clock gates. */ static struct samsung_gate_clock gate_clks[] __initdata = { GATE(CLK_ROTATOR, "rotator", "dout_hclkd", CLK_GATE_IP0, 29, 0, 0), GATE(CLK_FIMC2, "fimc2", "dout_hclkd", CLK_GATE_IP0, 26, 0, 0), GATE(CLK_FIMC1, "fimc1", "dout_hclkd", CLK_GATE_IP0, 25, 0, 0), GATE(CLK_FIMC0, "fimc0", "dout_hclkd", CLK_GATE_IP0, 24, 0, 0), GATE(CLK_PDMA0, "pdma0", "dout_hclkp", CLK_GATE_IP0, 3, 0, 0), GATE(CLK_MDMA, "mdma", "dout_hclkd", CLK_GATE_IP0, 2, 0, 0), GATE(CLK_SROMC, "sromc", "dout_hclkp", CLK_GATE_IP1, 26, 0, 0), GATE(CLK_NANDXL, "nandxl", "dout_hclkp", CLK_GATE_IP1, 24, 0, 0), GATE(CLK_USB_OTG, "usb_otg", "dout_hclkp", CLK_GATE_IP1, 16, 0, 0), GATE(CLK_TVENC, "tvenc", "dout_hclkd", CLK_GATE_IP1, 10, 0, 0), GATE(CLK_MIXER, "mixer", "dout_hclkd", CLK_GATE_IP1, 9, 0, 0), GATE(CLK_VP, "vp", "dout_hclkd", CLK_GATE_IP1, 8, 0, 0), GATE(CLK_FIMD, "fimd", "dout_hclkd", CLK_GATE_IP1, 0, 0, 0), GATE(CLK_HSMMC2, "hsmmc2", "dout_hclkp", CLK_GATE_IP2, 18, 0, 0),
* under the terms and conditions of the GNU General Public License, * version 2, as published by the Free Software Foundation. */ #include <linux/clk-provider.h> #include <linux/init.h> #include <linux/io.h> #include <linux/kernel.h> #include <linux/of.h> #include <dt-bindings/clock/pistachio-clk.h> #include "clk.h" static struct pistachio_gate pistachio_gates[] __initdata = { GATE(CLK_MIPS, "mips", "mips_div", 0x104, 0), GATE(CLK_AUDIO_IN, "audio_in", "audio_clk_in_gate", 0x104, 1), GATE(CLK_AUDIO, "audio", "audio_div", 0x104, 2), GATE(CLK_I2S, "i2s", "i2s_div", 0x104, 3), GATE(CLK_SPDIF, "spdif", "spdif_div", 0x104, 4), GATE(CLK_AUDIO_DAC, "audio_dac", "audio_dac_div", 0x104, 5), GATE(CLK_RPU_V, "rpu_v", "rpu_v_div", 0x104, 6), GATE(CLK_RPU_L, "rpu_l", "rpu_l_div", 0x104, 7), GATE(CLK_RPU_SLEEP, "rpu_sleep", "rpu_sleep_div", 0x104, 8), GATE(CLK_WIFI_PLL_GATE, "wifi_pll_gate", "wifi_pll_mux", 0x104, 9), GATE(CLK_RPU_CORE, "rpu_core", "rpu_core_div", 0x104, 10), GATE(CLK_WIFI_ADC, "wifi_adc", "wifi_div8_mux", 0x104, 11), GATE(CLK_WIFI_DAC, "wifi_dac", "wifi_div4_mux", 0x104, 12), GATE(CLK_USB_PHY, "usb_phy", "usb_phy_div", 0x104, 13), GATE(CLK_ENET_IN, "enet_in", "enet_clk_in_gate", 0x104, 14), GATE(CLK_ENET, "enet", "enet_div", 0x104, 15),
DEF_CLK(OTGPHY, 0), [CLK_ID_PLL] = {.name = "noclk", 1}, DEF_CLK(APLL, PLL(0)), DEF_CLK(MPLL, PLL(0)), DEF_CLK(SCLKA, PARENT(APLL)), [CLK_ID_CPPCR] = {.name = "noclk", 1}, DEF_CLK(CCLK, CPCCR(0)), DEF_CLK(L2CLK, CPCCR(0)), DEF_CLK(H0CLK, CPCCR(H0DIV)), DEF_CLK(H2CLK, CPCCR(H2DIV)), DEF_CLK(PCLK, CPCCR(PDIV)), [CLK_ID_DEVICES] = {.name = "noclk", 1}, DEF_CLK(EFUSE, GATE(1) | PARENT(H2CLK)), DEF_CLK(OTG, GATE(3)), DEF_CLK(MSC0, GATE(4) | PARENT(CGU_MSC_MUX)), DEF_CLK(MSC1, GATE(5) | PARENT(CGU_MSC_MUX)), DEF_CLK(SSI0, GATE(6) | PARENT(CGU_SSI)), DEF_CLK(I2C0, GATE(7) | PARENT(PCLK)), DEF_CLK(I2C1, GATE(8) | PARENT(PCLK)), DEF_CLK(AIC, GATE(11) | PARENT(CGU_I2S)), DEF_CLK(SADC, GATE(13)), DEF_CLK(UART0, GATE(14) | PARENT(EXT1)), DEF_CLK(UART1, GATE(15) | PARENT(EXT1)), DEF_CLK(PDMA, GATE(21) | PARENT(CGU_SSI)), DEF_CLK(ISP, GATE(23) | PARENT(CGU_ISP)), DEF_CLK(DES, GATE(28)),
}; static struct samsung_div_clock top0_div_clks[] __initdata = { DIV(DOUT_ACLK_PERIC1, "dout_aclk_peric1_66", "mout_aclk_peric1_66", DIV_TOP03, 12, 6), DIV(DOUT_ACLK_PERIC0, "dout_aclk_peric0_66", "mout_aclk_peric0_66", DIV_TOP03, 20, 6), DIV(0, "dout_sclk_uart3", "mout_sclk_uart3", DIV_TOP0_PERIC3, 4, 4), DIV(0, "dout_sclk_uart2", "mout_sclk_uart2", DIV_TOP0_PERIC3, 8, 4), DIV(0, "dout_sclk_uart1", "mout_sclk_uart1", DIV_TOP0_PERIC3, 12, 4), DIV(0, "dout_sclk_uart0", "mout_sclk_uart0", DIV_TOP0_PERIC3, 16, 4), }; static struct samsung_gate_clock top0_gate_clks[] __initdata = { GATE(CLK_SCLK_UART3, "sclk_uart3", "dout_sclk_uart3", ENABLE_SCLK_TOP0_PERIC3, 4, 0, 0), GATE(CLK_SCLK_UART2, "sclk_uart2", "dout_sclk_uart2", ENABLE_SCLK_TOP0_PERIC3, 8, 0, 0), GATE(CLK_SCLK_UART1, "sclk_uart1", "dout_sclk_uart1", ENABLE_SCLK_TOP0_PERIC3, 12, 0, 0), GATE(CLK_SCLK_UART0, "sclk_uart0", "dout_sclk_uart0", ENABLE_SCLK_TOP0_PERIC3, 16, 0, 0), }; static struct samsung_fixed_factor_clock top0_fixed_factor_clks[] __initdata = { FFACTOR(0, "ffac_top0_bus0_pll_div2", "mout_top0_bus0_pll", 1, 2, 0), FFACTOR(0, "ffac_top0_bus1_pll_div2", "mout_top0_bus1_pll", 1, 2, 0), FFACTOR(0, "ffac_top0_cc_pll_div2", "mout_top0_cc_pll", 1, 2, 0), FFACTOR(0, "ffac_top0_mfc_pll_div2", "mout_top0_mfc_pll", 1, 2, 0), };
/* mux clocks */ struct samsung_mux_clock exynos5440_mux_clks[] __initdata = { MUX(none, "mout_spi", mout_spi_p, MISC_DOUT1, 5, 1), MUX_A(arm_clk, "arm_clk", mout_armclk_p, CPU_CLK_STATUS, 0, 1, "armclk"), }; /* divider clocks */ struct samsung_div_clock exynos5440_div_clks[] __initdata = { DIV(spi_baud, "div_spi", "mout_spi", MISC_DOUT1, 3, 2), }; /* gate clocks */ struct samsung_gate_clock exynos5440_gate_clks[] __initdata = { GATE(pb0_250, "pb0_250", "div250", CLKEN_OV_VAL, 3, 0, 0), GATE(pr0_250, "pr0_250", "div250", CLKEN_OV_VAL, 4, 0, 0), GATE(pr1_250, "pr1_250", "div250", CLKEN_OV_VAL, 5, 0, 0), GATE(b_250, "b_250", "div250", CLKEN_OV_VAL, 9, 0, 0), GATE(b_125, "b_125", "div125", CLKEN_OV_VAL, 10, 0, 0), GATE(b_200, "b_200", "div200", CLKEN_OV_VAL, 11, 0, 0), GATE(sata, "sata", "div200", CLKEN_OV_VAL, 12, 0, 0), GATE(usb, "usb", "div200", CLKEN_OV_VAL, 13, 0, 0), GATE(gmac0, "gmac0", "div200", CLKEN_OV_VAL, 14, 0, 0), GATE(cs250, "cs250", "div250", CLKEN_OV_VAL, 19, 0, 0), GATE(pb0_250_o, "pb0_250_o", "pb0_250", CLKEN_OV_VAL, 3, 0, 0), GATE(pr0_250_o, "pr0_250_o", "pr0_250", CLKEN_OV_VAL, 4, 0, 0), GATE(pr1_250_o, "pr1_250_o", "pr1_250", CLKEN_OV_VAL, 5, 0, 0), GATE(b_250_o, "b_250_o", "b_250", CLKEN_OV_VAL, 9, 0, 0), GATE(b_125_o, "b_125_o", "b_125", CLKEN_OV_VAL, 10, 0, 0), GATE(b_200_o, "b_200_o", "b_200", CLKEN_OV_VAL, 11, 0, 0),
DIV(0, "dout_aclk550_cam", "mout_aclk550_cam", DIV_TOP8, 16, 3), DIV(0, "dout_aclkfl1_550_cam", "mout_aclkfl1_550_cam", DIV_TOP8, 20, 3), DIV(0, "dout_aclk432_cam", "mout_aclk432_cam", DIV_TOP8, 24, 3), DIV(0, "dout_aclk432_scaler", "mout_aclk432_scaler", DIV_TOP8, 28, 3), DIV(0, "dout_osc_div", "fin_pll", DIV_TOP9, 20, 3), DIV(0, "dout_sclk_sw", "sclk_spll", DIV_TOP9, 24, 6), }; static struct samsung_gate_clock exynos5800_gate_clks[] __initdata = { GATE(CLK_ACLK550_CAM, "aclk550_cam", "mout_user_aclk550_cam", GATE_BUS_TOP, 24, 0, 0), GATE(CLK_ACLK432_SCALER, "aclk432_scaler", "mout_user_aclk432_scaler", GATE_BUS_TOP, 27, 0, 0), }; static struct samsung_mux_clock exynos5420_mux_clks[] __initdata = { MUX(0, "sclk_bpll", mout_bpll_p, TOP_SPARE2, 0, 1), MUX(0, "mout_aclk400_wcore_bpll", mout_aclk400_wcore_bpll_p, TOP_SPARE2, 4, 1), MUX(0, "mout_aclk400_isp", mout_group1_p, SRC_TOP0, 0, 2), MUX_A(0, "mout_aclk400_mscl", mout_group1_p, SRC_TOP0, 4, 2, "aclk400_mscl"), MUX(0, "mout_aclk400_wcore", mout_group1_p, SRC_TOP0, 16, 2), MUX(0, "mout_aclk100_noc", mout_group1_p, SRC_TOP0, 20, 2),
static struct samsung_div_clock s3c2443_common_dividers[] __initdata = { DIV_T(0, "mdivclk", "xti", CLKDIV0, 6, 3, mdivclk_d), DIV(0, "prediv", "msysclk", CLKDIV0, 4, 2), DIV_T(HCLK, "hclk", "prediv", CLKDIV0, 0, 2, hclk_d), DIV(PCLK, "pclk", "hclk", CLKDIV0, 2, 1), DIV(0, "div_hsspi0_epll", "esysclk", CLKDIV1, 24, 2), DIV(0, "div_fimd", "esysclk", CLKDIV1, 16, 8), DIV(0, "div_i2s0", "esysclk", CLKDIV1, 12, 4), DIV(0, "div_uart", "esysclk", CLKDIV1, 8, 4), DIV(0, "div_hsmmc1", "esysclk", CLKDIV1, 6, 2), DIV(0, "div_usbhost", "esysclk", CLKDIV1, 4, 2), }; static struct samsung_gate_clock s3c2443_common_gates[] __initdata = { GATE(SCLK_HSMMC_EXT, "sclk_hsmmcext", "ext", SCLKCON, 13, 0, 0), GATE(SCLK_HSMMC1, "sclk_hsmmc1", "div_hsmmc1", SCLKCON, 12, 0, 0), GATE(SCLK_FIMD, "sclk_fimd", "div_fimd", SCLKCON, 10, 0, 0), GATE(SCLK_I2S0, "sclk_i2s0", "mux_i2s0", SCLKCON, 9, 0, 0), GATE(SCLK_UART, "sclk_uart", "div_uart", SCLKCON, 8, 0, 0), GATE(SCLK_USBH, "sclk_usbhost", "div_usbhost", SCLKCON, 1, 0, 0), GATE(HCLK_DRAM, "dram", "hclk", HCLKCON, 19, CLK_IGNORE_UNUSED, 0), GATE(HCLK_SSMC, "ssmc", "hclk", HCLKCON, 18, CLK_IGNORE_UNUSED, 0), GATE(HCLK_HSMMC1, "hsmmc1", "hclk", HCLKCON, 16, 0, 0), GATE(HCLK_USBD, "usb-device", "hclk", HCLKCON, 12, 0, 0), GATE(HCLK_USBH, "usb-host", "hclk", HCLKCON, 11, 0, 0), GATE(HCLK_LCD, "lcd", "hclk", HCLKCON, 9, 0, 0), GATE(HCLK_DMA5, "dma5", "hclk", HCLKCON, 5, CLK_IGNORE_UNUSED, 0), GATE(HCLK_DMA4, "dma4", "hclk", HCLKCON, 4, CLK_IGNORE_UNUSED, 0), GATE(HCLK_DMA3, "dma3", "hclk", HCLKCON, 3, CLK_IGNORE_UNUSED, 0), GATE(HCLK_DMA2, "dma2", "hclk", HCLKCON, 2, CLK_IGNORE_UNUSED, 0),
DIV(none, "div_mpwm", "div_isp1", E4X12_DIV_ISP1, 0, 3), DIV_F(div_mcuisp0, "div_mcuisp0", "aclk400_mcuisp", E4X12_DIV_ISP1, 4, 3, CLK_GET_RATE_NOCACHE, 0), DIV_F(div_mcuisp1, "div_mcuisp1", "div_mcuisp0", E4X12_DIV_ISP1, 8, 3, CLK_GET_RATE_NOCACHE, 0), DIV(sclk_fimg2d, "sclk_fimg2d", "mout_g2d", DIV_DMC1, 0, 4), }; /* list of gate clocks supported in all exynos4 soc's */ static struct samsung_gate_clock exynos4_gate_clks[] __initdata = { /* * After all Exynos4 based platforms are migrated to use device tree, * the device name and clock alias names specified below for some * of the clocks can be removed. */ GATE(sclk_hdmi, "sclk_hdmi", "mout_hdmi", SRC_MASK_TV, 0, 0, 0), GATE(sclk_spdif, "sclk_spdif", "mout_spdif", SRC_MASK_PERIL1, 8, 0, 0), GATE(jpeg, "jpeg", "aclk160", GATE_IP_CAM, 6, 0, 0), GATE(mie0, "mie0", "aclk160", GATE_IP_LCD0, 1, 0, 0), GATE(dsim0, "dsim0", "aclk160", GATE_IP_LCD0, 3, 0, 0), GATE(fimd1, "fimd1", "aclk160", E4210_GATE_IP_LCD1, 0, 0, 0), GATE(mie1, "mie1", "aclk160", E4210_GATE_IP_LCD1, 1, 0, 0), GATE(dsim1, "dsim1", "aclk160", E4210_GATE_IP_LCD1, 3, 0, 0), GATE(smmu_fimd1, "smmu_fimd1", "aclk160", E4210_GATE_IP_LCD1, 4, 0, 0), GATE(tsi, "tsi", "aclk133", GATE_IP_FSYS, 4, 0, 0), GATE(sromc, "sromc", "aclk133", GATE_IP_FSYS, 11, 0, 0), GATE(sclk_g3d, "sclk_g3d", "div_g3d", GATE_IP_G3D, 0, CLK_SET_RATE_PARENT, 0), GATE(usb_device, "usb_device", "aclk133", GATE_IP_FSYS, 13, 0, 0), GATE(onenand, "onenand", "aclk133", GATE_IP_FSYS, 15, 0, 0), GATE(nfcon, "nfcon", "aclk133", GATE_IP_FSYS, 16, 0, 0),
/* mux clocks */ static struct samsung_mux_clock exynos5440_mux_clks[] __initdata = { MUX(0, "mout_spi", mout_spi_p, MISC_DOUT1, 5, 1), MUX_A(CLK_ARM_CLK, "arm_clk", mout_armclk_p, CPU_CLK_STATUS, 0, 1, "armclk"), }; /* divider clocks */ static struct samsung_div_clock exynos5440_div_clks[] __initdata = { DIV(CLK_SPI_BAUD, "div_spi", "mout_spi", MISC_DOUT1, 3, 2), }; /* gate clocks */ static struct samsung_gate_clock exynos5440_gate_clks[] __initdata = { GATE(CLK_PB0_250, "pb0_250", "div250", CLKEN_OV_VAL, 3, 0, 0), GATE(CLK_PR0_250, "pr0_250", "div250", CLKEN_OV_VAL, 4, 0, 0), GATE(CLK_PR1_250, "pr1_250", "div250", CLKEN_OV_VAL, 5, 0, 0), GATE(CLK_B_250, "b_250", "div250", CLKEN_OV_VAL, 9, 0, 0), GATE(CLK_B_125, "b_125", "div125", CLKEN_OV_VAL, 10, 0, 0), GATE(CLK_B_200, "b_200", "div200", CLKEN_OV_VAL, 11, 0, 0), GATE(CLK_SATA, "sata", "div200", CLKEN_OV_VAL, 12, 0, 0), GATE(CLK_USB, "usb", "div200", CLKEN_OV_VAL, 13, 0, 0), GATE(CLK_GMAC0, "gmac0", "div200", CLKEN_OV_VAL, 14, 0, 0), GATE(CLK_CS250, "cs250", "div250", CLKEN_OV_VAL, 19, 0, 0), GATE(CLK_PB0_250_O, "pb0_250_o", "pb0_250", CLKEN_OV_VAL, 3, 0, 0), GATE(CLK_PR0_250_O, "pr0_250_o", "pr0_250", CLKEN_OV_VAL, 4, 0, 0), GATE(CLK_PR1_250_O, "pr1_250_o", "pr1_250", CLKEN_OV_VAL, 5, 0, 0), GATE(CLK_B_250_O, "b_250_o", "b_250", CLKEN_OV_VAL, 9, 0, 0), GATE(CLK_B_125_O, "b_125_o", "b_125", CLKEN_OV_VAL, 10, 0, 0), GATE(CLK_B_200_O, "b_200_o", "b_200", CLKEN_OV_VAL, 11, 0, 0),
static void i80286_interrupt_descriptor(i80286_state *cpustate,UINT16 number, int hwint, int error) { UINT16 desc[3], gatedesc[3]={0,0,0}, gatesel; UINT8 r; UINT32 addr; if(!PM) return PREFIX86(_interrupt)(cpustate, number); if ((number<<3)>=cpustate->idtr.limit) throw TRAP(GENERAL_PROTECTION_FAULT,(number*8+2+(hwint&&1))); desc[0] = ReadWord(cpustate->idtr.base+(number<<3)); desc[1] = ReadWord(cpustate->idtr.base+(number<<3)+2); desc[2] = ReadWord(cpustate->idtr.base+(number<<3)+4); r = RIGHTS(desc); if (!hwint && (DPL(r)<CPL)) throw TRAP(GENERAL_PROTECTION_FAULT,(number*8+2+(hwint&&1))); if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT,(number*8+2+(hwint&&1))); gatesel = GATESEL(desc); switch (GATE(r)) { case TASKGATE: i80286_switch_task(cpustate, gatesel, CALL); if((hwint == 1) && (error != -1)) PUSH(error); i80286_load_flags(cpustate, cpustate->flags, CPL); break; case INTGATE: case TRAPGATE: if ((addr = i80286_selector_address(cpustate,gatesel)) == -1) throw TRAP(GENERAL_PROTECTION_FAULT,(IDXTBL(gatesel)+(hwint&&1))); gatedesc[0] = ReadWord(addr); gatedesc[1] = ReadWord(addr+2); gatedesc[2] = ReadWord(addr+4); r = RIGHTS(gatedesc); if (!CODE(r) || !SEGDESC(r)) throw TRAP(GENERAL_PROTECTION_FAULT,(IDXTBL(gatesel)+(hwint&&1))); if (DPL(r)>CPL) throw TRAP(GENERAL_PROTECTION_FAULT,(IDXTBL(gatesel)+(hwint&&1))); if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT,(IDXTBL(gatesel)+(hwint&&1))); if (GATEOFF(desc) > LIMIT(gatedesc)) throw TRAP(GENERAL_PROTECTION_FAULT,(int)(hwint&&1)); if (!CONF(r)&&(DPL(r)<CPL)) { // inner call UINT16 tss_ss, tss_sp, oldss, oldsp; tss_ss = ReadWord(cpustate->tr.base+TSS_SS0*2+(DPL(r)*4)); tss_sp = ReadWord(cpustate->tr.base+TSS_SP0*2+(DPL(r)*4)); oldss = cpustate->sregs[SS]; oldsp = cpustate->regs.w[SP]; i80286_data_descriptor_full(cpustate, SS, tss_ss, DPL(r), TRAP(INVALID_TSS,(IDXTBL(tss_ss)+(hwint&&1))), tss_sp-((error != -1)?12:10), (error != -1)?12:10); cpustate->regs.w[SP] = tss_sp; PUSH(oldss); PUSH(oldsp); } else i80286_check_permission(cpustate, SS, cpustate->regs.w[SP]-((error != -1)?8:6), (error != -1)?8:6, I80286_READ); SET_ACC(gatedesc); WriteWord(addr+4, gatedesc[2]); PREFIX(_pushf(cpustate)); PUSH(cpustate->sregs[CS]); PUSH(cpustate->pc-cpustate->base[CS]); if((hwint == 1) && (error != -1)) PUSH(error); cpustate->sregs[CS]=IDXTBL(gatesel) | DPL(r); cpustate->limit[CS]=LIMIT(gatedesc); cpustate->base[CS]=BASE(gatedesc); cpustate->rights[CS]=RIGHTS(gatedesc); cpustate->pc=(cpustate->base[CS]+GATEOFF(desc))&AMASK; cpustate->TF = 0; cpustate->flags &= ~0x4000; if (GATE(RIGHTS(desc)) == INTGATE) cpustate->IF = 0; CHANGE_PC(cpustate->pc); break; default: throw TRAP(GENERAL_PROTECTION_FAULT,(number*8+2+(hwint&&1))); } }
static void PREFIX286(_0fpre)(i8086_state *cpustate) { unsigned next = FETCHOP; UINT16 ModRM, desc[3]; UINT16 tmp, msw, sel; UINT8 r; UINT32 addr; switch (next) { case 0: if (!PM) throw TRAP(ILLEGAL_INSTRUCTION,-1); ModRM=FETCHOP; switch (ModRM&0x38) { case 0: /* sldt */ PutRMWord(ModRM, cpustate->ldtr.sel); break; case 8: /* str */ PutRMWord(ModRM, cpustate->tr.sel); break; case 0x10: /* lldt */ if (CPL!=0) throw TRAP(GENERAL_PROTECTION_FAULT,0); sel=GetRMWord(ModRM); if (TBL(sel)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel)); if (IDXTBL(sel)) { if (IDX(sel)>=cpustate->gdtr.limit) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel)); addr = cpustate->gdtr.base + IDX(sel); desc[0] = ReadWord(addr); desc[1] = ReadWord(addr+2); desc[2] = ReadWord(addr+4); r = RIGHTS(desc); if (SEGDESC(r) || (GATE(r) != LDTDESC)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel)); if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT,IDXTBL(sel)); } else { desc[0] = 0; desc[1] = 0; desc[2] = 0; } cpustate->ldtr.sel=sel; cpustate->ldtr.limit=LIMIT(desc); cpustate->ldtr.base=BASE(desc); cpustate->ldtr.rights=RIGHTS(desc); break; case 0x18: /* ltr */ if (CPL!=0) throw TRAP(GENERAL_PROTECTION_FAULT,0); sel=GetRMWord(ModRM); if ((addr = i80286_selector_address(cpustate,sel)) == -1) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel)); desc[0] = ReadWord(addr); desc[1] = ReadWord(addr+2); desc[2] = ReadWord(addr+4); r = RIGHTS(desc); if (SEGDESC(r) || (GATE(r) != TSSDESCIDLE)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(sel)); if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT,IDXTBL(sel)); desc[2] |= 0x200; // mark busy WriteWord(addr+4, desc[2]); cpustate->tr.sel=sel; cpustate->tr.limit=LIMIT(desc); cpustate->tr.base=BASE(desc); cpustate->tr.rights=RIGHTS(desc); break; case 0x20: /* verr */ tmp=GetRMWord(ModRM); if ((addr = i80286_selector_address(cpustate,tmp)) == -1) cpustate->ZeroVal = 1; else { desc[2] = ReadWord(addr+4); r = RIGHTS(desc); cpustate->ZeroVal = i80286_verify(cpustate, tmp, I80286_READ, RIGHTS(desc), 0); cpustate->ZeroVal = cpustate->ZeroVal || (CODE(r) && CONF(r) ? 0 : (DPL(r)<PMAX(RPL(tmp),CPL))); } break; case 0x28: /* verw */ tmp=GetRMWord(ModRM); if ((addr = i80286_selector_address(cpustate,tmp)) == -1) cpustate->ZeroVal = 1; else { desc[2] = ReadWord(addr+4); r = RIGHTS(desc); cpustate->ZeroVal = i80286_verify(cpustate, tmp, I80286_WRITE, RIGHTS(desc), 0); cpustate->ZeroVal = cpustate->ZeroVal || (DPL(r)<PMAX(RPL(tmp),CPL)); } break; default: throw TRAP(ILLEGAL_INSTRUCTION,-1); break; } break; case 1: /* lgdt, lldt in protected mode privilege level 0 required else common protection failure 0xd */ ModRM = FETCHOP; switch (ModRM&0x38) { case 0: /* sgdt */ PutRMWord(ModRM,cpustate->gdtr.limit); PutRMWordOffset(2,cpustate->gdtr.base&0xffff); PutRMWordOffset(4,0xff00|cpustate->gdtr.base>>16); break; case 8: /* sidt */ PutRMWord(ModRM,cpustate->idtr.limit); PutRMWordOffset(2,cpustate->idtr.base&0xffff); PutRMWordOffset(4,0xff00|cpustate->idtr.base>>16); break; case 0x10: /* lgdt */ if (PM&&(CPL!=0)) throw TRAP(GENERAL_PROTECTION_FAULT,0); cpustate->gdtr.limit=GetRMWord(ModRM); cpustate->gdtr.base=GetRMWordOffset(2)|(GetRMByteOffset(4)<<16); break; case 0x18: /* lidt */ if (PM&&(CPL!=0)) throw TRAP(GENERAL_PROTECTION_FAULT,0); cpustate->idtr.limit=GetRMWord(ModRM); cpustate->idtr.base=GetRMWordOffset(2)|(GetRMByteOffset(4)<<16); break; case 0x20: /* smsw */ PutRMWord(ModRM, cpustate->msw); break; case 0x30: /* lmsw */ if (PM&&(CPL!=0)) throw TRAP(GENERAL_PROTECTION_FAULT,0); msw = GetRMWord(ModRM); if (!PM&&(msw&1)) cpustate->sregs[CS] = IDX(cpustate->sregs[CS]); // cheat and set cpl to 0 cpustate->msw=(cpustate->msw&1)|msw; break; default: throw TRAP(ILLEGAL_INSTRUCTION,-1); break; } break; case 2: /* LAR */ if (!PM) throw TRAP(ILLEGAL_INSTRUCTION,-1); ModRM = FETCHOP; tmp=GetRMWord(ModRM); if ((addr = i80286_selector_address(cpustate,tmp)) == -1) cpustate->ZeroVal = 1; else { desc[2] = ReadWord(addr+4); r = RIGHTS(desc); if (DPL(r)>=PMAX(RPL(tmp),CPL)) { cpustate->ZeroVal = 0; // rights are expected to be in upper byte RegWord(ModRM) = r << 8; } else cpustate->ZeroVal = 1; } break; case 3: /* LSL */ if (!PM) throw TRAP(ILLEGAL_INSTRUCTION,-1); ModRM = FETCHOP; tmp=GetRMWord(ModRM); if ((addr = i80286_selector_address(cpustate,tmp)) == -1) cpustate->ZeroVal = 1; else { desc[2] = ReadWord(addr+4); r = RIGHTS(desc); if (!SEGDESC(r) && (GATE(r) >= CALLGATE)) cpustate->ZeroVal = 1; // not valid for gates else if (DPL(r)>=PMAX(RPL(tmp),CPL)) { cpustate->ZeroVal = 0; RegWord(ModRM) = ReadWord(addr); } else cpustate->ZeroVal = 1; } break; case 5: /* loadall */ if (PM&&(CPL!=0)) throw TRAP(GENERAL_PROTECTION_FAULT,0); cpustate->msw = (cpustate->msw&1)|ReadWord(0x806); cpustate->tr.sel = ReadWord(0x816); tmp = ReadWord(0x818); ExpandFlags(tmp); cpustate->flags = tmp; cpustate->flags = CompressFlags(); cpustate->pc = ReadWord(0x81a); cpustate->ldtr.sel = ReadWord(0x81c); cpustate->sregs[DS] = ReadWord(0x81e); cpustate->sregs[SS] = ReadWord(0x820); cpustate->sregs[CS] = ReadWord(0x822); cpustate->sregs[ES] = ReadWord(0x824); cpustate->regs.w[DI] = ReadWord(0x826); cpustate->regs.w[SI] = ReadWord(0x828); cpustate->regs.w[BP] = ReadWord(0x82a); cpustate->regs.w[SP] = ReadWord(0x82c); cpustate->regs.w[BX] = ReadWord(0x82e); cpustate->regs.w[DX] = ReadWord(0x830); cpustate->regs.w[CX] = ReadWord(0x832); cpustate->regs.w[AX] = ReadWord(0x834); // loadall uses base-rights-limit order #define LOADDESC(addr, sreg) { desc[1] = ReadWord(addr); desc[2] = ReadWord(addr+2); desc[0] = ReadWord(addr+4); \ cpustate->base[sreg] = BASE(desc); cpustate->rights[sreg] = RIGHTS(desc); \ cpustate->limit[sreg] = LIMIT(desc); } LOADDESC(0x836, ES); LOADDESC(0x83C, CS); LOADDESC(0x842, SS); LOADDESC(0x848, DS); #undef LOADDESC // void cast supresses warning #define LOADDESC(addr, reg, r) { desc[1] = ReadWord(addr); desc[2] = ReadWord(addr+2); desc[0] = ReadWord(addr+4); \ cpustate->reg.base = BASE(desc); (void)(r); cpustate->reg.limit = LIMIT(desc); } LOADDESC(0x84e, gdtr, 1); LOADDESC(0x854, ldtr, cpustate->ldtr.rights = RIGHTS(desc)); LOADDESC(0x85a, idtr, 1); LOADDESC(0x860, tr, cpustate->tr.rights = RIGHTS(desc)); #undef LOADDESC cpustate->pc = (cpustate->pc + cpustate->base[CS]) & AMASK; CHANGE_PC(cpustate->pc); break; case 6: /* clts */ if (PM&&(CPL!=0)) throw TRAP(GENERAL_PROTECTION_FAULT,0); cpustate->msw&=~8; break; default: throw TRAP(ILLEGAL_INSTRUCTION,-1); break; } }
RST_DEVICES_V, RST_DEVICES_W, RST_DEVICES_X, }; #define L(n) ((0 * 32) + (n)) #define H(n) ((1 * 32) + (n)) #define U(n) ((2 * 32) + (n)) #define V(n) ((3 * 32) + (n)) #define W(n) ((4 * 32) + (n)) #define X(n) ((5 * 32) + (n)) static struct pgate_def pgate_def[] = { /* bank L -> 0-31 */ /* GATE(CPU, "cpu", "clk_m", L(0)), */ GATE(ISPB, "ispb", "clk_m", L(3)), GATE(RTC, "rtc", "clk_s", L(4)), GATE(TIMER, "timer", "clk_m", L(5)), GATE(UARTA, "uarta", "pc_uarta" , L(6)), GATE(UARTB, "uartb", "pc_uartb", L(7)), GATE(VFIR, "vfir", "pc_vfir", L(7)), /* GATE(GPIO, "gpio", "clk_m", L(8)), */ GATE(SDMMC2, "sdmmc2", "pc_sdmmc2", L(9)), GATE(SPDIF_OUT, "spdif_out", "pc_spdif_out", L(10)), GATE(SPDIF_IN, "spdif_in", "pc_spdif_in", L(10)), GATE(I2S1, "i2s1", "pc_i2s1", L(11)), GATE(I2C1, "i2c1", "pc_i2c1", L(12)), GATE(SDMMC1, "sdmmc1", "pc_sdmmc1", L(14)), GATE(SDMMC4, "sdmmc4", "pc_sdmmc4", L(15)), GATE(PWM, "pwm", "pc_pwm", L(17)), GATE(I2S2, "i2s2", "pc_i2s2", L(18)),
DIV_TOPC3, 8, 4), DIV(DOUT_SCLK_CC_PLL, "dout_sclk_cc_pll", "mout_topc_cc_pll", DIV_TOPC3, 12, 4), DIV(DOUT_SCLK_MFC_PLL, "dout_sclk_mfc_pll", "mout_topc_mfc_pll", DIV_TOPC3, 16, 4), DIV(DOUT_SCLK_AUD_PLL, "dout_sclk_aud_pll", "mout_topc_aud_pll", DIV_TOPC3, 28, 4), }; static struct samsung_pll_rate_table pll1460x_24mhz_tbl[] __initdata = { PLL_36XX_RATE(491520000, 20, 1, 0, 31457), {}, }; static struct samsung_gate_clock topc_gate_clks[] __initdata = { GATE(ACLK_CCORE_133, "aclk_ccore_133", "dout_aclk_ccore_133", ENABLE_ACLK_TOPC0, 4, 0, 0), GATE(ACLK_MSCL_532, "aclk_mscl_532", "dout_aclk_mscl_532", ENABLE_ACLK_TOPC1, 20, 0, 0), GATE(ACLK_PERIS_66, "aclk_peris_66", "dout_aclk_peris_66", ENABLE_ACLK_TOPC1, 24, 0, 0), GATE(SCLK_AUD_PLL, "sclk_aud_pll", "dout_sclk_aud_pll", ENABLE_SCLK_TOPC1, 20, 0, 0), GATE(SCLK_MFC_PLL_B, "sclk_mfc_pll_b", "dout_sclk_mfc_pll", ENABLE_SCLK_TOPC1, 17, 0, 0), GATE(SCLK_MFC_PLL_A, "sclk_mfc_pll_a", "dout_sclk_mfc_pll", ENABLE_SCLK_TOPC1, 16, 0, 0), GATE(SCLK_BUS1_PLL_B, "sclk_bus1_pll_b", "dout_sclk_bus1_pll", ENABLE_SCLK_TOPC1, 13, 0, 0),
COMPOSITE(SCLK_RTC32K, "clk_rtc32k", mux_2plls_xin24m_p, 0, RK3328_CLKSEL_CON(38), 14, 2, MFLAGS, 0, 14, DFLAGS, RK3328_CLKGATE_CON(0), 11, GFLAGS), /* PD_MISC */ MUX(HDMIPHY, "hdmiphy", mux_hdmiphy_p, CLK_SET_RATE_PARENT, RK3328_MISC_CON, 13, 1, MFLAGS), MUX(USB480M, "usb480m", mux_usb480m_p, CLK_SET_RATE_PARENT, RK3328_MISC_CON, 15, 1, MFLAGS), /* * Clock-Architecture Diagram 2 */ /* PD_CORE */ GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(0), 0, GFLAGS), GATE(0, "gpll_core", "gpll", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(0), 2, GFLAGS), GATE(0, "dpll_core", "dpll", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(0), 1, GFLAGS), GATE(0, "npll_core", "npll", CLK_IGNORE_UNUSED, RK3328_CLKGATE_CON(0), 12, GFLAGS), COMPOSITE_NOMUX(0, "pclk_dbg", "armclk", CLK_IGNORE_UNUSED, RK3328_CLKSEL_CON(1), 0, 4, DFLAGS | CLK_DIVIDER_READ_ONLY, RK3328_CLKGATE_CON(7), 0, GFLAGS), COMPOSITE_NOMUX(0, "aclk_core", "armclk", CLK_IGNORE_UNUSED, RK3328_CLKSEL_CON(1), 4, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, RK3328_CLKGATE_CON(7), 1, GFLAGS), GATE(0, "aclk_core_niu", "aclk_core", 0, RK3328_CLKGATE_CON(13), 0, GFLAGS), GATE(0, "aclk_gic400", "aclk_core", CLK_IGNORE_UNUSED,
{ .val = 2, .div = 4 }, { .val = 3, .div = 6 }, { .val = 4, .div = 8 }, { .val = 5, .div = 10 }, { .val = 6, .div = 12 }, { .val = 7, .div = 14 }, { /* sentinel */ }, }; static struct samsung_div_clock s3c2410_common_dividers[] __initdata = { DIV_T(0, "div_slow", "xti", CLKSLOW, 0, 3, divslow_d), DIV(PCLK, "pclk", "hclk", CLKDIVN, 0, 1), }; static struct samsung_gate_clock s3c2410_common_gates[] __initdata = { GATE(PCLK_SPI, "spi", "pclk", CLKCON, 18, 0, 0), GATE(PCLK_I2S, "i2s", "pclk", CLKCON, 17, 0, 0), GATE(PCLK_I2C, "i2c", "pclk", CLKCON, 16, 0, 0), GATE(PCLK_ADC, "adc", "pclk", CLKCON, 15, 0, 0), GATE(PCLK_RTC, "rtc", "pclk", CLKCON, 14, 0, 0), GATE(PCLK_GPIO, "gpio", "pclk", CLKCON, 13, CLK_IGNORE_UNUSED, 0), GATE(PCLK_UART2, "uart2", "pclk", CLKCON, 12, 0, 0), GATE(PCLK_UART1, "uart1", "pclk", CLKCON, 11, 0, 0), GATE(PCLK_UART0, "uart0", "pclk", CLKCON, 10, 0, 0), GATE(PCLK_SDI, "sdi", "pclk", CLKCON, 9, 0, 0), GATE(PCLK_PWM, "pwm", "pclk", CLKCON, 8, 0, 0), GATE(HCLK_USBD, "usb-device", "hclk", CLKCON, 7, 0, 0), GATE(HCLK_USBH, "usb-host", "hclk", CLKCON, 6, 0, 0), GATE(HCLK_LCD, "lcd", "hclk", CLKCON, 5, 0, 0), GATE(HCLK_NAND, "nand", "hclk", CLKCON, 4, 0, 0), };
/* 2 ^ (val + 1) */ static struct clk_div_table div_core_peri_t[] = { { .val = 0, .div = 2 }, { .val = 1, .div = 4 }, { .val = 2, .div = 8 }, { .val = 3, .div = 16 }, { /* sentinel */ }, }; static struct rockchip_clk_branch common_clk_branches[] __initdata = { /* * Clock-Architecture Diagram 2 */ GATE(0, "gpll_armclk", "gpll", 0, RK2928_CLKGATE_CON(0), 1, GFLAGS), /* these two are set by the cpuclk and should not be changed */ COMPOSITE_NOMUX_DIVTBL(CORE_PERI, "core_peri", "armclk", 0, RK2928_CLKSEL_CON(0), 6, 2, DFLAGS | CLK_DIVIDER_READ_ONLY, div_core_peri_t, RK2928_CLKGATE_CON(0), 0, GFLAGS), COMPOSITE(0, "aclk_vepu", mux_pll_src_cpll_gpll_p, 0, RK2928_CLKSEL_CON(32), 7, 1, MFLAGS, 0, 5, DFLAGS, RK2928_CLKGATE_CON(3), 9, GFLAGS), GATE(0, "hclk_vepu", "aclk_vepu", 0, RK2928_CLKGATE_CON(3), 10, GFLAGS), COMPOSITE(0, "aclk_vdpu", mux_pll_src_cpll_gpll_p, 0, RK2928_CLKSEL_CON(32), 15, 1, MFLAGS, 8, 5, DFLAGS, RK2928_CLKGATE_CON(3), 11, GFLAGS), GATE(0, "hclk_vdpu", "aclk_vdpu", 0,
{ .val = 1, .div = 2 }, { .val = 3, .div = 4 }, { /* sentinel */}, }; #define MFLAGS CLK_MUX_HIWORD_MASK #define DFLAGS CLK_DIVIDER_HIWORD_MASK #define GFLAGS (CLK_GATE_HIWORD_MASK | CLK_GATE_SET_TO_DISABLE) #define IFLAGS ROCKCHIP_INVERTER_HIWORD_MASK static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { /* * Clock-Architecture Diagram 1 */ GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(0), 1, GFLAGS), GATE(0, "gpll_core", "gpll", CLK_IGNORE_UNUSED, RK3288_CLKGATE_CON(0), 2, GFLAGS), COMPOSITE_NOMUX(0, "armcore0", "armclk", CLK_IGNORE_UNUSED, RK3288_CLKSEL_CON(36), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, RK3288_CLKGATE_CON(12), 0, GFLAGS), COMPOSITE_NOMUX(0, "armcore1", "armclk", CLK_IGNORE_UNUSED, RK3288_CLKSEL_CON(36), 4, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, RK3288_CLKGATE_CON(12), 1, GFLAGS), COMPOSITE_NOMUX(0, "armcore2", "armclk", CLK_IGNORE_UNUSED, RK3288_CLKSEL_CON(36), 8, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, RK3288_CLKGATE_CON(12), 2, GFLAGS), COMPOSITE_NOMUX(0, "armcore3", "armclk", CLK_IGNORE_UNUSED, RK3288_CLKSEL_CON(36), 12, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, RK3288_CLKGATE_CON(12), 3, GFLAGS),
DIV_F(0, "div_mmc_pre1", "div_mmc1", DIV_FSYS1, 24, 8, CLK_SET_RATE_PARENT, 0), DIV_F(0, "div_mmc_pre2", "div_mmc2", DIV_FSYS2, 8, 8, CLK_SET_RATE_PARENT, 0), DIV(0, "div_uart0", "mout_uart0", DIV_PERIC0, 0, 4), DIV(0, "div_uart1", "mout_uart1", DIV_PERIC0, 4, 4), DIV(0, "div_uart2", "mout_uart2", DIV_PERIC0, 8, 4), DIV(0, "div_uart3", "mout_uart3", DIV_PERIC0, 12, 4), DIV(0, "aclk200", "mout_aclk200", DIV_TOP0, 12, 3), DIV(0, "aclk400", "mout_aclk400", DIV_TOP0, 24, 3), }; static struct samsung_gate_clock exynos5410_gate_clks[] __initdata = { GATE(CLK_MCT, "mct", "aclk66", GATE_IP_PERIS, 18, 0, 0), GATE(CLK_SCLK_MMC0, "sclk_mmc0", "div_mmc_pre0", SRC_MASK_FSYS, 0, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_MMC1, "sclk_mmc1", "div_mmc_pre1", SRC_MASK_FSYS, 4, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_MMC2, "sclk_mmc2", "div_mmc_pre2", SRC_MASK_FSYS, 8, CLK_SET_RATE_PARENT, 0), GATE(CLK_MMC0, "sdmmc0", "aclk200", GATE_BUS_FSYS0, 12, 0, 0), GATE(CLK_MMC1, "sdmmc1", "aclk200", GATE_BUS_FSYS0, 13, 0, 0), GATE(CLK_MMC2, "sdmmc2", "aclk200", GATE_BUS_FSYS0, 14, 0, 0), GATE(CLK_UART0, "uart0", "aclk66", GATE_IP_PERIC, 0, 0, 0), GATE(CLK_UART1, "uart1", "aclk66", GATE_IP_PERIC, 1, 0, 0), GATE(CLK_UART2, "uart2", "aclk66", GATE_IP_PERIC, 2, 0, 0),
E4X12_GATE_ISP0, E4X12_GATE_ISP1, }; static struct samsung_div_clock exynos4x12_isp_div_clks[] = { DIV(CLK_ISP_DIV_ISP0, "div_isp0", "aclk200", E4X12_DIV_ISP0, 0, 3), DIV(CLK_ISP_DIV_ISP1, "div_isp1", "aclk200", E4X12_DIV_ISP0, 4, 3), DIV(CLK_ISP_DIV_MCUISP0, "div_mcuisp0", "aclk400_mcuisp", E4X12_DIV_ISP1, 4, 3), DIV(CLK_ISP_DIV_MCUISP1, "div_mcuisp1", "div_mcuisp0", E4X12_DIV_ISP1, 8, 3), DIV(0, "div_mpwm", "div_isp1", E4X12_DIV_ISP1, 0, 3), }; static struct samsung_gate_clock exynos4x12_isp_gate_clks[] = { GATE(CLK_ISP_FIMC_ISP, "isp", "aclk200", E4X12_GATE_ISP0, 0, 0, 0), GATE(CLK_ISP_FIMC_DRC, "drc", "aclk200", E4X12_GATE_ISP0, 1, 0, 0), GATE(CLK_ISP_FIMC_FD, "fd", "aclk200", E4X12_GATE_ISP0, 2, 0, 0), GATE(CLK_ISP_FIMC_LITE0, "lite0", "aclk200", E4X12_GATE_ISP0, 3, 0, 0), GATE(CLK_ISP_FIMC_LITE1, "lite1", "aclk200", E4X12_GATE_ISP0, 4, 0, 0), GATE(CLK_ISP_MCUISP, "mcuisp", "aclk200", E4X12_GATE_ISP0, 5, 0, 0), GATE(CLK_ISP_GICISP, "gicisp", "aclk200", E4X12_GATE_ISP0, 7, 0, 0), GATE(CLK_ISP_SMMU_ISP, "smmu_isp", "aclk200", E4X12_GATE_ISP0, 8, 0, 0), GATE(CLK_ISP_SMMU_DRC, "smmu_drc", "aclk200", E4X12_GATE_ISP0, 9, 0, 0), GATE(CLK_ISP_SMMU_FD, "smmu_fd", "aclk200", E4X12_GATE_ISP0, 10, 0, 0), GATE(CLK_ISP_SMMU_LITE0, "smmu_lite0", "aclk200", E4X12_GATE_ISP0, 11, 0, 0), GATE(CLK_ISP_SMMU_LITE1, "smmu_lite1", "aclk200", E4X12_GATE_ISP0, 12, 0, 0), GATE(CLK_ISP_PPMUISPMX, "ppmuispmx", "aclk200", E4X12_GATE_ISP0, 20, 0, 0),
DIV(CLK_DIV_I2S1, "div_i2s1", "sclk_audio1", DIV_PERIC5, 0, 6), DIV(CLK_DIV_I2S2, "div_i2s2", "sclk_audio2", DIV_PERIC5, 8, 6), }; static struct samsung_gate_clock exynos5250_gate_clks[] __initdata = { /* * NOTE: Following table is sorted by (clock domain, register address, * bitfield shift) triplet in ascending order. When adding new entries, * please make sure that the order is kept, to avoid merge conflicts * and make further work with defined data easier. */ /* * CMU_ACP */ GATE(CLK_MDMA0, "mdma0", "div_aclk266", GATE_IP_ACP, 1, 0, 0), GATE(CLK_SSS, "sss", "div_aclk266", GATE_IP_ACP, 2, 0, 0), GATE(CLK_G2D, "g2d", "div_aclk200", GATE_IP_ACP, 3, 0, 0), GATE(CLK_SMMU_MDMA0, "smmu_mdma0", "div_aclk266", GATE_IP_ACP, 5, 0, 0), /* * CMU_TOP */ GATE(CLK_SCLK_CAM_BAYER, "sclk_cam_bayer", "div_cam_bayer", SRC_MASK_GSCL, 12, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_CAM0, "sclk_cam0", "div_cam0", SRC_MASK_GSCL, 16, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_CAM1, "sclk_cam1", "div_cam1", SRC_MASK_GSCL, 20, CLK_SET_RATE_PARENT, 0), GATE(CLK_SCLK_GSCL_WA, "sclk_gscl_wa", "div_gscl_wa", SRC_MASK_GSCL, 24, CLK_SET_RATE_PARENT, 0),
NODIV("sor0", mux_clkm_plldp_sor0lvds, CLK_SOURCE_SOR0, 14, 3, 182, 0, tegra_clk_sor0, &sor0_lock), UART("uarta", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTA, 6, tegra_clk_uarta), UART("uartb", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTB, 7, tegra_clk_uartb), UART("uartc", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTC, 55, tegra_clk_uartc), UART("uartd", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTD, 65, tegra_clk_uartd), UART("uarte", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTE, 66, tegra_clk_uarte), XUSB("xusb_host_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_host_src), XUSB("xusb_falcon_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_falcon_src), XUSB("xusb_fs_src", mux_clkm_48M_pllp_480M, CLK_SOURCE_XUSB_FS_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_fs_src), XUSB("xusb_ss_src", mux_clkm_pllre_clk32_480M_pllc_ref, CLK_SOURCE_XUSB_SS_SRC, 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_ss_src), NODIV("xusb_hs_src", mux_ss_60M, CLK_SOURCE_XUSB_SS_SRC, 25, MASK(1), 143, TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_hs_src, NULL), XUSB("xusb_dev_src", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_xusb_dev_src), }; static struct tegra_periph_init_data gate_clks[] = { GATE("rtc", "clk_32k", 4, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_rtc, 0), GATE("timer", "clk_m", 5, 0, tegra_clk_timer, 0), GATE("isp", "clk_m", 23, 0, tegra_clk_isp, 0), GATE("vcp", "clk_m", 29, 0, tegra_clk_vcp, 0), GATE("apbdma", "clk_m", 34, 0, tegra_clk_apbdma, 0), GATE("kbc", "clk_32k", 36, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, tegra_clk_kbc, 0), GATE("fuse", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse, 0), GATE("fuse_burn", "clk_m", 39, TEGRA_PERIPH_ON_APB, tegra_clk_fuse_burn, 0), GATE("kfuse", "clk_m", 40, TEGRA_PERIPH_ON_APB, tegra_clk_kfuse, 0), GATE("apbif", "clk_m", 107, TEGRA_PERIPH_ON_APB, tegra_clk_apbif, 0), GATE("hda2hdmi", "clk_m", 128, TEGRA_PERIPH_ON_APB, tegra_clk_hda2hdmi, 0), GATE("bsea", "clk_m", 62, 0, tegra_clk_bsea, 0), GATE("bsev", "clk_m", 63, 0, tegra_clk_bsev, 0), GATE("mipi-cal", "clk_m", 56, 0, tegra_clk_mipi_cal, 0), GATE("usbd", "clk_m", 22, 0, tegra_clk_usbd, 0), GATE("usb2", "clk_m", 58, 0, tegra_clk_usb2, 0),
static void i80286_switch_task(i80286_state *cpustate, UINT16 ntask, int type) { UINT16 ndesc[3], desc[3], ntss[22], otss[22]; UINT8 r, lr; UINT32 naddr, oaddr, ldtaddr; int i; logerror("This program uses TSSs, how rare. Please report this to the developers.\n"); if (TBL(ntask)) throw TRAP(INVALID_TSS,IDXTBL(ntask)); if ((naddr = i80286_selector_address(cpustate,ntask)) == -1) throw TRAP(INVALID_TSS,IDXTBL(ntask)); oaddr = i80286_selector_address(cpustate,cpustate->tr.sel); ndesc[0] = ReadWord(naddr); ndesc[1] = ReadWord(naddr+2); ndesc[2] = ReadWord(naddr+4); desc[2] = ReadWord(oaddr+4); r = RIGHTS(ndesc); if (SEGDESC(r) || ((GATE(r) & ~2) != TSSDESCIDLE)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(ntask)); if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT, IDXTBL(ntask)); if (LIMIT(ndesc) < 43) throw TRAP(INVALID_TSS,IDXTBL(ntask)); for (i = 0; i < 44; i+=2) ntss[i/2] = ReadWord(BASE(ndesc)+i); cpustate->flags = CompressFlags(); if (type == CALL) WriteWord(BASE(ndesc)+TSS_BACK*2, cpustate->tr.sel); if (type == IRET) cpustate->flags &= ~0x4000; otss[TSS_IP] = cpustate->pc-cpustate->base[CS]; otss[TSS_FLAG] = cpustate->flags; otss[TSS_AX] = cpustate->regs.w[AX]; otss[TSS_CX] = cpustate->regs.w[CX]; otss[TSS_DX] = cpustate->regs.w[DX]; otss[TSS_BX] = cpustate->regs.w[BX]; otss[TSS_SP] = cpustate->regs.w[SP]; otss[TSS_BP] = cpustate->regs.w[BP]; otss[TSS_SI] = cpustate->regs.w[SI]; otss[TSS_DI] = cpustate->regs.w[DI]; otss[TSS_ES] = cpustate->sregs[ES]; otss[TSS_CS] = cpustate->sregs[CS]; otss[TSS_SS] = cpustate->sregs[SS]; otss[TSS_DS] = cpustate->sregs[DS]; otss[TSS_LDT] = cpustate->ldtr.sel; for (i = 14; i < 44; i+=2) WriteWord(cpustate->tr.base+i, otss[i/2]); // jmp does both if (type != CALL) { desc[2] &= ~0x200; // mark idle WriteWord(oaddr+4, desc[2]); } if (type != IRET) { ndesc[2] |= 0x200; WriteWord(naddr+4, ndesc[2]); } cpustate->tr.sel=ntask; cpustate->tr.limit=LIMIT(ndesc); cpustate->tr.base=BASE(ndesc); cpustate->tr.rights=RIGHTS(ndesc); cpustate->flags = ntss[TSS_FLAG]; cpustate->regs.w[AX] = ntss[TSS_AX]; cpustate->regs.w[CX] = ntss[TSS_CX]; cpustate->regs.w[DX] = ntss[TSS_DX]; cpustate->regs.w[BX] = ntss[TSS_BX]; cpustate->regs.w[SP] = ntss[TSS_SP]; cpustate->regs.w[BP] = ntss[TSS_BP]; cpustate->regs.w[SI] = ntss[TSS_SI]; cpustate->regs.w[DI] = ntss[TSS_DI]; if (TBL(ntss[TSS_LDT])) throw TRAP(INVALID_TSS,IDXTBL(ntss[TSS_LDT])); if (IDXTBL(ntss[TSS_LDT])) { if ((ldtaddr = i80286_selector_address(cpustate,ntss[TSS_LDT])) == -1) throw TRAP(INVALID_TSS,IDXTBL(ntss[TSS_LDT])); desc[0] = ReadWord(ldtaddr); desc[1] = ReadWord(ldtaddr+2); desc[2] = ReadWord(ldtaddr+4); lr = RIGHTS(desc); if (SEGDESC(lr) || (GATE(lr) != LDTDESC)) throw TRAP(INVALID_TSS,IDXTBL(ntss[TSS_LDT])); if (!PRES(lr)) throw TRAP(INVALID_TSS,IDXTBL(ntss[TSS_LDT])); cpustate->ldtr.sel=ntss[TSS_LDT]; cpustate->ldtr.limit=LIMIT(desc); cpustate->ldtr.base=BASE(desc); cpustate->ldtr.rights=RIGHTS(desc); } else { cpustate->ldtr.sel=0; cpustate->ldtr.limit=0; cpustate->ldtr.base=0; cpustate->ldtr.rights=0; } if (type == CALL) cpustate->flags |= 0x4000; cpustate->msw |= 8; i80286_data_descriptor_full(cpustate, SS, ntss[TSS_SS], RPL(ntss[TSS_CS]), TRAP(INVALID_TSS,IDXTBL(ntss[TSS_SS])), 0, 0); cpustate->sregs[CS] = IDXTBL(cpustate->sregs[CS]) | RPL(ntss[TSS_CS]); // fixme try { i80286_code_descriptor(cpustate, ntss[TSS_CS], ntss[TSS_IP], 0); } catch(UINT32 e) { int error_code = e & 0xffff; if(error_code == GENERAL_PROTECTION_FAULT) e = TRAP(INVALID_TSS,(e >> 16)); // #NP fault is correct throw e; } i80286_data_descriptor_full(cpustate, ES, ntss[TSS_ES], RPL(ntss[TSS_CS]), TRAP(INVALID_TSS,IDXTBL(ntss[TSS_ES])), 0, 0); i80286_data_descriptor_full(cpustate, DS, ntss[TSS_DS], RPL(ntss[TSS_CS]), TRAP(INVALID_TSS,IDXTBL(ntss[TSS_DS])), 0, 0); }
static struct rockchip_clk_branch rk1108_i2s2_fracmux __initdata = MUX(0, "i2s2_pre", mux_i2s2_p, CLK_SET_RATE_PARENT, RK1108_CLKSEL_CON(7), 12, 2, MFLAGS); static struct rockchip_clk_branch rk1108_clk_branches[] __initdata = { MUX(0, "hdmi_phy", mux_hdmiphy_phy_p, CLK_SET_RATE_PARENT, RK1108_MISC_CON, 13, 2, MFLAGS), MUX(0, "usb480m", mux_usb480m_pre_p, CLK_SET_RATE_PARENT, RK1108_MISC_CON, 15, 2, MFLAGS), /* * Clock-Architecture Diagram 2 */ /* PD_CORE */ GATE(0, "dpll_core", "dpll", CLK_IGNORE_UNUSED, RK1108_CLKGATE_CON(0), 1, GFLAGS), GATE(0, "apll_core", "apll", CLK_IGNORE_UNUSED, RK1108_CLKGATE_CON(0), 0, GFLAGS), GATE(0, "gpll_core", "gpll", CLK_IGNORE_UNUSED, RK1108_CLKGATE_CON(0), 2, GFLAGS), COMPOSITE_NOMUX(0, "pclken_dbg", "armclk", CLK_IGNORE_UNUSED, RK1108_CLKSEL_CON(1), 4, 4, DFLAGS | CLK_DIVIDER_READ_ONLY, RK1108_CLKGATE_CON(0), 5, GFLAGS), COMPOSITE_NOMUX(ACLK_ENMCORE, "aclkenm_core", "armclk", CLK_IGNORE_UNUSED, RK1108_CLKSEL_CON(1), 0, 3, DFLAGS | CLK_DIVIDER_READ_ONLY, RK1108_CLKGATE_CON(0), 4, GFLAGS), GATE(ACLK_CORE, "aclk_core", "aclkenm_core", CLK_IGNORE_UNUSED, RK1108_CLKGATE_CON(11), 0, GFLAGS), GATE(0, "pclk_dbg", "pclken_dbg", CLK_IGNORE_UNUSED, RK1108_CLKGATE_CON(11), 1, GFLAGS),
static void i80286_code_descriptor(i80286_state *cpustate, UINT16 selector, UINT16 offset, int gate) { if (PM) { UINT16 desc[3]; UINT8 r; UINT32 addr; /* selector format 15..3 number/address in descriptor table 2: 0 global, 1 local descriptor table 1,0: requested privileg level must be higher or same as current privileg level in code selector */ if ((addr = i80286_selector_address(cpustate,selector)) == -1) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector)); desc[0] = ReadWord(addr); desc[1] = ReadWord(addr+2); desc[2] = ReadWord(addr+4); r = RIGHTS(desc); if (SEGDESC(r)) { if (!CODE(r)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector)); if (CONF(r)) { if(DPL(r)>CPL) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector)); } else if ((RPL(selector)>CPL) || (DPL(r)!=CPL)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector)); if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT,IDXTBL(selector)); // this order is important if (offset > LIMIT(desc)) throw TRAP(GENERAL_PROTECTION_FAULT, 0); SET_ACC(desc); WriteWord(addr+4, desc[2]); cpustate->sregs[CS]=IDXTBL(selector) | CPL; cpustate->limit[CS]=LIMIT(desc); cpustate->base[CS]=BASE(desc); cpustate->rights[CS]=RIGHTS(desc); cpustate->pc=cpustate->base[CS]+offset; } else { // systemdescriptor UINT16 gatedesc[3]={0,0,0}; UINT16 gatesel = GATESEL(desc); if (!gate) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector)); // tss cs must be segment if (DPL(r) < PMAX(CPL,RPL(selector))) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector)); if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT, IDXTBL(selector)); switch (GATE(r)) { case CALLGATE: if ((addr = i80286_selector_address(cpustate,gatesel)) == -1) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(gatesel)); gatedesc[0] = ReadWord(addr); gatedesc[1] = ReadWord(addr+2); gatedesc[2] = ReadWord(addr+4); r = RIGHTS(gatedesc); if (!CODE(r) || !SEGDESC(r)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(gatesel)); if (DPL(r)>CPL) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(gatesel)); if (!PRES(r)) throw TRAP(SEG_NOT_PRESENT,IDXTBL(gatesel)); if (GATEOFF(desc) > LIMIT(gatedesc)) throw TRAP(GENERAL_PROTECTION_FAULT,0); if (!CONF(r)&&(DPL(r)<CPL)) { // inner call UINT16 tss_ss, tss_sp, oldss, oldsp; UINT32 oldstk; int i; if(gate == JMP) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(gatesel)); // can't jmp to inner tss_ss = ReadWord(cpustate->tr.base+TSS_SS0*2+(DPL(r)*4)); tss_sp = ReadWord(cpustate->tr.base+TSS_SP0*2+(DPL(r)*4)); oldss = cpustate->sregs[SS]; oldsp = cpustate->regs.w[SP]; oldstk = cpustate->base[SS] + oldsp; i80286_data_descriptor_full(cpustate, SS, tss_ss, DPL(r), TRAP(INVALID_TSS,IDXTBL(tss_ss)), tss_sp-8-(GATECNT(desc)*2), 8+(GATECNT(desc)*2)); cpustate->regs.w[SP] = tss_sp; PUSH(oldss); PUSH(oldsp); for (i = GATECNT(desc)-1; i >= 0; i--) PUSH(ReadWord(oldstk+(i*2))); } else i80286_check_permission(cpustate, SS, cpustate->regs.w[SP]-4, 4, I80286_READ); SET_ACC(gatedesc); WriteWord(addr+4, gatedesc[2]); cpustate->sregs[CS]=IDXTBL(gatesel) | DPL(r); cpustate->limit[CS]=LIMIT(gatedesc); cpustate->base[CS]=BASE(gatedesc); cpustate->rights[CS]=RIGHTS(gatedesc); cpustate->pc=(cpustate->base[CS]+GATEOFF(desc))&AMASK; break; case TASKGATE: selector = gatesel; if ((addr = i80286_selector_address(cpustate,selector)) == -1) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector)); desc[2] = ReadWord(addr+4); r = RIGHTS(desc); if (SEGDESC(r) || (GATE(r) != TSSDESCIDLE)) throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector)); case TSSDESCIDLE: i80286_switch_task(cpustate, selector, gate); i80286_load_flags(cpustate, cpustate->flags, CPL); break; default: throw TRAP(GENERAL_PROTECTION_FAULT,IDXTBL(selector)); } } } else { cpustate->sregs[CS]=selector; cpustate->base[CS]=selector<<4; cpustate->rights[CS]=0x9a; cpustate->limit[CS]=0xffff; cpustate->pc=(cpustate->base[CS]+offset)&AMASK; } }