提交 b85c14fb 编写于 作者: L Linus Torvalds

Merge tag 'fixes-non-critical' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc

Pull non-critical arm-soc bug fixes from Arnd Bergmann:
 "These were submitted as bug fixes before v3.5 but not considered
  important enough to be included in it."

* tag 'fixes-non-critical' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (29 commits)
  ARM:vt8500: Convert to use .restart and remove arch_reset()
  ARM: davinci: da8xx: fix interrupt handling
  ARM: OMAP2+: fix CONFIG_CPU_IDLE dependency on CONFIG_PM
  ARM: mxs/tx28: fix odd include
  ARM: OMAP: remove unused cpu detection macros
  ARM: OMAP: fix typos related to OMAP330
  ARM: OMAP7XX:  Remove omap730.h and omap850.h
  ARM: OMAP2+: fix naming collision of variable nr_irqs
  ARM: OMAP: omap2plus_defconfig: Enable EXT4 support
  ARM: OMAP depends on MMU
  arm: omap3: am35x: Set proper powerdomain states
  ARM: OMAP AM35x: clockdomain data: Fix clockdomain dependencies
  ARM: OMAP AM35x: EMAC/MDIO integration: Add Davinci EMAC/MDIO hwmod support
  ARM: OMAP: AM35xx: fix UART4 softreset
  ARM: OMAP AM35xx: clock and hwmod data: fix UART4 data
  ARM: OMAP AM35xx: clock and hwmod data: fix AM35xx HSOTGUSB hwmod
  ARM: OMAP: Fix dts files w/ status property: "disable" -> "disabled"
  ARM: OMAP: beagle: Set USB Host Port 1 to OMAP_USBHS_PORT_MODE_UNUSED
  ARM: OMAP2: twl-common: Fix compiler warning
  ARM: OMAP: fix the ads7846 init code
  ...
......@@ -936,6 +936,7 @@ config ARCH_DAVINCI
config ARCH_OMAP
bool "TI OMAP"
depends on MMU
select HAVE_CLK
select ARCH_REQUIRE_GPIOLIB
select ARCH_HAS_CPUFREQ
......
......@@ -61,9 +61,9 @@
};
&mmc2 {
status = "disable";
status = "disabled";
};
&mmc3 {
status = "disable";
status = "disabled";
};
......@@ -74,15 +74,15 @@
};
&mmc2 {
status = "disable";
status = "disabled";
};
&mmc3 {
status = "disable";
status = "disabled";
};
&mmc4 {
status = "disable";
status = "disabled";
};
&mmc5 {
......
......@@ -147,11 +147,11 @@
};
&mmc3 {
status = "disable";
status = "disabled";
};
&mmc4 {
status = "disable";
status = "disabled";
};
&mmc5 {
......
......@@ -196,6 +196,7 @@ CONFIG_RTC_DRV_TWL4030=y
CONFIG_EXT2_FS=y
CONFIG_EXT3_FS=y
# CONFIG_EXT3_FS_XATTR is not set
CONFIG_EXT4_FS=y
CONFIG_QUOTA=y
CONFIG_QFMT_V2=y
CONFIG_MSDOS_FS=y
......
......@@ -30,12 +30,10 @@
#endif
#if defined(CONFIG_CP_INTC)
1001: ldr \irqnr, [\base, #0x80] /* get irq number */
mov \tmp, \irqnr, lsr #31
and \irqnr, \irqnr, #0xff /* irq is in bits 0-9 */
mov \tmp, \irqnr, lsr #3
and \tmp, \tmp, #0xfc
add \tmp, \tmp, #0x280 /* get the register offset */
ldr \irqstat, [\base, \tmp] /* get the intc status */
cmp \irqstat, #0x0
and \tmp, \tmp, #0x1
cmp \tmp, #0x1
#endif
1002:
.endm
......@@ -91,8 +91,8 @@ static void __init edb93xx_register_i2c(void)
ep93xx_register_i2c(&edb93xx_i2c_gpio_data,
edb93xxa_i2c_board_info,
ARRAY_SIZE(edb93xxa_i2c_board_info));
} else if (machine_is_edb9307() || machine_is_edb9312() ||
machine_is_edb9315()) {
} else if (machine_is_edb9302() || machine_is_edb9307()
|| machine_is_edb9312() || machine_is_edb9315()) {
ep93xx_register_i2c(&edb93xx_i2c_gpio_data,
edb93xx_i2c_board_info,
ARRAY_SIZE(edb93xx_i2c_board_info));
......
......@@ -11,7 +11,7 @@
#include <linux/gpio.h>
#include <mach/iomux-mx28.h>
#include "../devices-mx28.h"
#include "devices-mx28.h"
#include "module-tx28.h"
......
......@@ -35,6 +35,7 @@ config ARCH_OMAP3
select CPU_V7
select USB_ARCH_HAS_EHCI if USB_SUPPORT
select ARCH_HAS_OPP
select PM_RUNTIME if CPU_IDLE
select PM_OPP if PM
select ARM_CPU_SUSPEND if PM
select MULTI_IRQ_HANDLER
......@@ -52,6 +53,7 @@ config ARCH_OMAP4
select PL310_ERRATA_727915
select ARM_ERRATA_720789
select ARCH_HAS_OPP
select PM_RUNTIME if CPU_IDLE
select PM_OPP if PM
select USB_ARCH_HAS_EHCI if USB_SUPPORT
select ARM_CPU_SUSPEND if PM
......
......@@ -66,9 +66,7 @@ ifeq ($(CONFIG_PM),y)
obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o
obj-$(CONFIG_ARCH_OMAP2) += sleep24xx.o
obj-$(CONFIG_ARCH_OMAP3) += pm34xx.o sleep34xx.o
obj-$(CONFIG_ARCH_OMAP3) += cpuidle34xx.o
obj-$(CONFIG_ARCH_OMAP4) += pm44xx.o omap-mpuss-lowpower.o
obj-$(CONFIG_ARCH_OMAP4) += cpuidle44xx.o
obj-$(CONFIG_PM_DEBUG) += pm-debug.o
obj-$(CONFIG_OMAP_SMARTREFLEX) += sr_device.o smartreflex.o
obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3) += smartreflex-class3.o
......@@ -82,6 +80,11 @@ endif
endif
ifeq ($(CONFIG_CPU_IDLE),y)
obj-$(CONFIG_ARCH_OMAP3) += cpuidle34xx.o
obj-$(CONFIG_ARCH_OMAP4) += cpuidle44xx.o
endif
# PRCM
obj-y += prm_common.o
obj-$(CONFIG_ARCH_OMAP2) += prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o
......
......@@ -15,27 +15,13 @@
* General Public License for more details.
*/
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/davinci_emac.h>
#include <linux/platform_device.h>
#include <plat/irqs.h>
#include <asm/system.h>
#include <plat/omap_device.h>
#include <mach/am35xx.h>
#include "control.h"
static struct mdio_platform_data am35xx_emac_mdio_pdata;
static struct resource am35xx_emac_mdio_resources[] = {
DEFINE_RES_MEM(AM35XX_IPSS_EMAC_BASE + AM35XX_EMAC_MDIO_OFFSET, SZ_4K),
};
static struct platform_device am35xx_emac_mdio_device = {
.name = "davinci_mdio",
.id = 0,
.num_resources = ARRAY_SIZE(am35xx_emac_mdio_resources),
.resource = am35xx_emac_mdio_resources,
.dev.platform_data = &am35xx_emac_mdio_pdata,
};
#include "am35xx-emac.h"
static void am35xx_enable_emac_int(void)
{
......@@ -69,41 +55,57 @@ static struct emac_platform_data am35xx_emac_pdata = {
.interrupt_disable = am35xx_disable_emac_int,
};
static struct resource am35xx_emac_resources[] = {
DEFINE_RES_MEM(AM35XX_IPSS_EMAC_BASE, 0x30000),
DEFINE_RES_IRQ(INT_35XX_EMAC_C0_RXTHRESH_IRQ),
DEFINE_RES_IRQ(INT_35XX_EMAC_C0_RX_PULSE_IRQ),
DEFINE_RES_IRQ(INT_35XX_EMAC_C0_TX_PULSE_IRQ),
DEFINE_RES_IRQ(INT_35XX_EMAC_C0_MISC_PULSE_IRQ),
};
static struct mdio_platform_data am35xx_mdio_pdata;
static struct platform_device am35xx_emac_device = {
.name = "davinci_emac",
.id = -1,
.num_resources = ARRAY_SIZE(am35xx_emac_resources),
.resource = am35xx_emac_resources,
.dev = {
.platform_data = &am35xx_emac_pdata,
},
};
static int __init omap_davinci_emac_dev_init(struct omap_hwmod *oh,
void *pdata, int pdata_len)
{
struct platform_device *pdev;
pdev = omap_device_build(oh->class->name, 0, oh, pdata, pdata_len,
NULL, 0, false);
if (IS_ERR(pdev)) {
WARN(1, "Can't build omap_device for %s:%s.\n",
oh->class->name, oh->name);
return PTR_ERR(pdev);
}
return 0;
}
void __init am35xx_emac_init(unsigned long mdio_bus_freq, u8 rmii_en)
{
struct omap_hwmod *oh;
u32 v;
int err;
int ret;
am35xx_emac_pdata.rmii_en = rmii_en;
am35xx_emac_mdio_pdata.bus_freq = mdio_bus_freq;
err = platform_device_register(&am35xx_emac_device);
if (err) {
pr_err("AM35x: failed registering EMAC device: %d\n", err);
oh = omap_hwmod_lookup("davinci_mdio");
if (!oh) {
pr_err("Could not find davinci_mdio hwmod\n");
return;
}
am35xx_mdio_pdata.bus_freq = mdio_bus_freq;
ret = omap_davinci_emac_dev_init(oh, &am35xx_mdio_pdata,
sizeof(am35xx_mdio_pdata));
if (ret) {
pr_err("Could not build davinci_mdio hwmod device\n");
return;
}
err = platform_device_register(&am35xx_emac_mdio_device);
if (err) {
pr_err("AM35x: failed registering EMAC MDIO device: %d\n", err);
platform_device_unregister(&am35xx_emac_device);
oh = omap_hwmod_lookup("davinci_emac");
if (!oh) {
pr_err("Could not find davinci_emac hwmod\n");
return;
}
am35xx_emac_pdata.rmii_en = rmii_en;
ret = omap_davinci_emac_dev_init(oh, &am35xx_emac_pdata,
sizeof(am35xx_emac_pdata));
if (ret) {
pr_err("Could not build davinci_emac hwmod device\n");
return;
}
......
......@@ -218,9 +218,6 @@ static struct twl4030_gpio_platform_data sdp2430_gpio_data = {
};
static struct twl4030_platform_data sdp2430_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
/* platform_data for children goes here */
.gpio = &sdp2430_gpio_data,
.vmmc1 = &sdp2430_vmmc1,
......
......@@ -433,7 +433,7 @@ static struct platform_device *omap3_beagle_devices[] __initdata = {
static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
.port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
......
......@@ -93,9 +93,6 @@ static struct twl4030_usb_data omap3logic_usb_data = {
static struct twl4030_platform_data omap3logic_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
/* platform_data for children goes here */
.gpio = &omap3logic_gpio_data,
.vmmc1 = &omap3logic_vmmc1,
......
......@@ -2490,13 +2490,13 @@ static struct clk uart4_fck = {
};
static struct clk uart4_fck_am35xx = {
.name = "uart4_fck",
.ops = &clkops_omap2_dflt_wait,
.parent = &per_48m_fck,
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
.enable_bit = OMAP3430_EN_UART4_SHIFT,
.clkdm_name = "core_l4_clkdm",
.recalc = &followparent_recalc,
.name = "uart4_fck",
.ops = &clkops_omap2_dflt_wait,
.parent = &core_48m_fck,
.enable_reg = OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
.enable_bit = AM35XX_EN_UART4_SHIFT,
.clkdm_name = "core_l4_clkdm",
.recalc = &followparent_recalc,
};
static struct clk gpt2_fck = {
......@@ -3201,8 +3201,12 @@ static struct clk vpfe_fck = {
};
/*
* The UART1/2 functional clock acts as the functional
* clock for UART4. No separate fclk control available.
* The UART1/2 functional clock acts as the functional clock for
* UART4. No separate fclk control available. XXX Well now we have a
* uart4_fck that is apparently used as the UART4 functional clock,
* but it also seems that uart1_fck or uart2_fck are still needed, at
* least for UART4 softresets to complete. This really needs
* clarification.
*/
static struct clk uart4_ick_am35xx = {
.name = "uart4_ick",
......@@ -3474,12 +3478,12 @@ static struct omap_clk omap3xxx_clks[] = {
CLK(NULL, "ipss_ick", &ipss_ick, CK_AM35XX),
CLK(NULL, "rmii_ck", &rmii_ck, CK_AM35XX),
CLK(NULL, "pclk_ck", &pclk_ck, CK_AM35XX),
CLK("davinci_emac", NULL, &emac_ick, CK_AM35XX),
CLK("davinci_emac.0", NULL, &emac_ick, CK_AM35XX),
CLK("davinci_mdio.0", NULL, &emac_fck, CK_AM35XX),
CLK("vpfe-capture", "master", &vpfe_ick, CK_AM35XX),
CLK("vpfe-capture", "slave", &vpfe_fck, CK_AM35XX),
CLK("musb-am35x", "ick", &hsotgusb_ick_am35xx, CK_AM35XX),
CLK("musb-am35x", "fck", &hsotgusb_fck_am35xx, CK_AM35XX),
CLK(NULL, "hsotgusb_ick", &hsotgusb_ick_am35xx, CK_AM35XX),
CLK(NULL, "hsotgusb_fck", &hsotgusb_fck_am35xx, CK_AM35XX),
CLK(NULL, "hecc_ck", &hecc_ck, CK_AM35XX),
CLK(NULL, "uart4_ick", &uart4_ick_am35xx, CK_AM35XX),
CLK("omap_timer.1", "32k_ck", &omap_32k_fck, CK_3XXX),
......
......@@ -59,6 +59,12 @@ static struct clkdm_dep gfx_sgx_3xxx_wkdeps[] = {
{ NULL },
};
static struct clkdm_dep gfx_sgx_am35x_wkdeps[] = {
{ .clkdm_name = "mpu_clkdm" },
{ .clkdm_name = "wkup_clkdm" },
{ NULL },
};
/* 3430: PM_WKDEP_PER: CORE, IVA2, MPU, WKUP */
static struct clkdm_dep per_wkdeps[] = {
{ .clkdm_name = "core_l3_clkdm" },
......@@ -69,6 +75,14 @@ static struct clkdm_dep per_wkdeps[] = {
{ NULL },
};
static struct clkdm_dep per_am35x_wkdeps[] = {
{ .clkdm_name = "core_l3_clkdm" },
{ .clkdm_name = "core_l4_clkdm" },
{ .clkdm_name = "mpu_clkdm" },
{ .clkdm_name = "wkup_clkdm" },
{ NULL },
};
/* 3430ES2: PM_WKDEP_USBHOST: CORE, IVA2, MPU, WKUP */
static struct clkdm_dep usbhost_wkdeps[] = {
{ .clkdm_name = "core_l3_clkdm" },
......@@ -79,6 +93,14 @@ static struct clkdm_dep usbhost_wkdeps[] = {
{ NULL },
};
static struct clkdm_dep usbhost_am35x_wkdeps[] = {
{ .clkdm_name = "core_l3_clkdm" },
{ .clkdm_name = "core_l4_clkdm" },
{ .clkdm_name = "mpu_clkdm" },
{ .clkdm_name = "wkup_clkdm" },
{ NULL },
};
/* 3430 PM_WKDEP_MPU: CORE, IVA2, DSS, PER */
static struct clkdm_dep mpu_3xxx_wkdeps[] = {
{ .clkdm_name = "core_l3_clkdm" },
......@@ -89,6 +111,14 @@ static struct clkdm_dep mpu_3xxx_wkdeps[] = {
{ NULL },
};
static struct clkdm_dep mpu_am35x_wkdeps[] = {
{ .clkdm_name = "core_l3_clkdm" },
{ .clkdm_name = "core_l4_clkdm" },
{ .clkdm_name = "dss_clkdm" },
{ .clkdm_name = "per_clkdm" },
{ NULL },
};
/* 3430 PM_WKDEP_IVA2: CORE, MPU, WKUP, DSS, PER */
static struct clkdm_dep iva2_wkdeps[] = {
{ .clkdm_name = "core_l3_clkdm" },
......@@ -116,6 +146,12 @@ static struct clkdm_dep dss_wkdeps[] = {
{ NULL },
};
static struct clkdm_dep dss_am35x_wkdeps[] = {
{ .clkdm_name = "mpu_clkdm" },
{ .clkdm_name = "wkup_clkdm" },
{ NULL },
};
/* 3430: PM_WKDEP_NEON: MPU */
static struct clkdm_dep neon_wkdeps[] = {
{ .clkdm_name = "mpu_clkdm" },
......@@ -131,6 +167,11 @@ static struct clkdm_dep dss_sleepdeps[] = {
{ NULL },
};
static struct clkdm_dep dss_am35x_sleepdeps[] = {
{ .clkdm_name = "mpu_clkdm" },
{ NULL },
};
/* 3430: CM_SLEEPDEP_PER: MPU, IVA */
static struct clkdm_dep per_sleepdeps[] = {
{ .clkdm_name = "mpu_clkdm" },
......@@ -138,6 +179,11 @@ static struct clkdm_dep per_sleepdeps[] = {
{ NULL },
};
static struct clkdm_dep per_am35x_sleepdeps[] = {
{ .clkdm_name = "mpu_clkdm" },
{ NULL },
};
/* 3430ES2: CM_SLEEPDEP_USBHOST: MPU, IVA */
static struct clkdm_dep usbhost_sleepdeps[] = {
{ .clkdm_name = "mpu_clkdm" },
......@@ -145,6 +191,11 @@ static struct clkdm_dep usbhost_sleepdeps[] = {
{ NULL },
};
static struct clkdm_dep usbhost_am35x_sleepdeps[] = {
{ .clkdm_name = "mpu_clkdm" },
{ NULL },
};
/* 3430: CM_SLEEPDEP_CAM: MPU */
static struct clkdm_dep cam_sleepdeps[] = {
{ .clkdm_name = "mpu_clkdm" },
......@@ -175,6 +226,15 @@ static struct clockdomain mpu_3xxx_clkdm = {
.clktrctrl_mask = OMAP3430_CLKTRCTRL_MPU_MASK,
};
static struct clockdomain mpu_am35x_clkdm = {
.name = "mpu_clkdm",
.pwrdm = { .name = "mpu_pwrdm" },
.flags = CLKDM_CAN_HWSUP | CLKDM_CAN_FORCE_WAKEUP,
.dep_bit = OMAP3430_EN_MPU_SHIFT,
.wkdep_srcs = mpu_am35x_wkdeps,
.clktrctrl_mask = OMAP3430_CLKTRCTRL_MPU_MASK,
};
static struct clockdomain neon_clkdm = {
.name = "neon_clkdm",
.pwrdm = { .name = "neon_pwrdm" },
......@@ -210,6 +270,15 @@ static struct clockdomain sgx_clkdm = {
.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK,
};
static struct clockdomain sgx_am35x_clkdm = {
.name = "sgx_clkdm",
.pwrdm = { .name = "sgx_pwrdm" },
.flags = CLKDM_CAN_HWSUP_SWSUP,
.wkdep_srcs = gfx_sgx_am35x_wkdeps,
.sleepdep_srcs = gfx_sgx_sleepdeps,
.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_SGX_MASK,
};
/*
* The die-to-die clockdomain was documented in the 34xx ES1 TRM, but
* then that information was removed from the 34xx ES2+ TRM. It is
......@@ -261,6 +330,16 @@ static struct clockdomain dss_3xxx_clkdm = {
.clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK,
};
static struct clockdomain dss_am35x_clkdm = {
.name = "dss_clkdm",
.pwrdm = { .name = "dss_pwrdm" },
.flags = CLKDM_CAN_HWSUP_SWSUP,
.dep_bit = OMAP3430_PM_WKDEP_MPU_EN_DSS_SHIFT,
.wkdep_srcs = dss_am35x_wkdeps,
.sleepdep_srcs = dss_am35x_sleepdeps,
.clktrctrl_mask = OMAP3430_CLKTRCTRL_DSS_MASK,
};
static struct clockdomain cam_clkdm = {
.name = "cam_clkdm",
.pwrdm = { .name = "cam_pwrdm" },
......@@ -279,6 +358,15 @@ static struct clockdomain usbhost_clkdm = {
.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_USBHOST_MASK,
};
static struct clockdomain usbhost_am35x_clkdm = {
.name = "usbhost_clkdm",
.pwrdm = { .name = "core_pwrdm" },
.flags = CLKDM_CAN_HWSUP_SWSUP,
.wkdep_srcs = usbhost_am35x_wkdeps,
.sleepdep_srcs = usbhost_am35x_sleepdeps,
.clktrctrl_mask = OMAP3430ES2_CLKTRCTRL_USBHOST_MASK,
};
static struct clockdomain per_clkdm = {
.name = "per_clkdm",
.pwrdm = { .name = "per_pwrdm" },
......@@ -289,6 +377,16 @@ static struct clockdomain per_clkdm = {
.clktrctrl_mask = OMAP3430_CLKTRCTRL_PER_MASK,
};
static struct clockdomain per_am35x_clkdm = {
.name = "per_clkdm",
.pwrdm = { .name = "per_pwrdm" },
.flags = CLKDM_CAN_HWSUP_SWSUP,
.dep_bit = OMAP3430_EN_PER_SHIFT,
.wkdep_srcs = per_am35x_wkdeps,
.sleepdep_srcs = per_am35x_sleepdeps,
.clktrctrl_mask = OMAP3430_CLKTRCTRL_PER_MASK,
};
/*
* Disable hw supervised mode for emu_clkdm, because emu_pwrdm is
* switched of even if sdti is in use
......@@ -341,31 +439,44 @@ static struct clkdm_autodep clkdm_autodeps[] = {
}
};
static struct clkdm_autodep clkdm_am35x_autodeps[] = {
{
.clkdm = { .name = "mpu_clkdm" },
},
{
.clkdm = { .name = NULL },
}
};
/*
*
*/
static struct clockdomain *clockdomains_omap3430_common[] __initdata = {
static struct clockdomain *clockdomains_common[] __initdata = {
&wkup_common_clkdm,
&cm_common_clkdm,
&prm_common_clkdm,
&mpu_3xxx_clkdm,
&neon_clkdm,
&iva2_clkdm,
&d2d_clkdm,
&core_l3_3xxx_clkdm,
&core_l4_3xxx_clkdm,
&dss_3xxx_clkdm,
&cam_clkdm,
&per_clkdm,
&emu_clkdm,
&dpll1_clkdm,
&dpll2_clkdm,
&dpll3_clkdm,
&dpll4_clkdm,
NULL
};
static struct clockdomain *clockdomains_omap3430[] __initdata = {
&mpu_3xxx_clkdm,
&iva2_clkdm,
&d2d_clkdm,
&dss_3xxx_clkdm,
&cam_clkdm,
&per_clkdm,
&dpll2_clkdm,
NULL
};
static struct clockdomain *clockdomains_omap3430es1[] __initdata = {
&gfx_3430es1_clkdm,
NULL,
......@@ -378,21 +489,41 @@ static struct clockdomain *clockdomains_omap3430es2plus[] __initdata = {
NULL,
};
static struct clockdomain *clockdomains_am35x[] __initdata = {
&mpu_am35x_clkdm,
&sgx_am35x_clkdm,
&dss_am35x_clkdm,
&per_am35x_clkdm,
&usbhost_am35x_clkdm,
&dpll5_clkdm,
NULL
};
void __init omap3xxx_clockdomains_init(void)
{
struct clockdomain **sc;
unsigned int rev;
if (!cpu_is_omap34xx())
return;
clkdm_register_platform_funcs(&omap3_clkdm_operations);
clkdm_register_clkdms(clockdomains_omap3430_common);
clkdm_register_clkdms(clockdomains_common);
sc = (omap_rev() == OMAP3430_REV_ES1_0) ? clockdomains_omap3430es1 :
clockdomains_omap3430es2plus;
rev = omap_rev();
clkdm_register_clkdms(sc);
if (rev == AM35XX_REV_ES1_0 || rev == AM35XX_REV_ES1_1) {
clkdm_register_clkdms(clockdomains_am35x);
clkdm_register_autodeps(clkdm_am35x_autodeps);
} else {
clkdm_register_clkdms(clockdomains_omap3430);
sc = (rev == OMAP3430_REV_ES1_0) ?
clockdomains_omap3430es1 : clockdomains_omap3430es2plus;
clkdm_register_clkdms(sc);
clkdm_register_autodeps(clkdm_autodeps);
}
clkdm_register_autodeps(clkdm_autodeps);
clkdm_complete_init();
}
......@@ -169,8 +169,6 @@
/* AM35XX specific CM_ICLKEN1_CORE bits */
#define AM35XX_EN_IPSS_MASK (1 << 4)
#define AM35XX_EN_IPSS_SHIFT 4
#define AM35XX_EN_UART4_MASK (1 << 23)
#define AM35XX_EN_UART4_SHIFT 23
/* CM_ICLKEN2_CORE */
#define OMAP3430_EN_PKA_MASK (1 << 4)
......@@ -207,6 +205,8 @@
#define OMAP3430_ST_DES2_MASK (1 << 26)
#define OMAP3430_ST_MSPRO_SHIFT 23
#define OMAP3430_ST_MSPRO_MASK (1 << 23)
#define AM35XX_ST_UART4_SHIFT 23
#define AM35XX_ST_UART4_MASK (1 << 23)
#define OMAP3430_ST_HDQ_SHIFT 22
#define OMAP3430_ST_HDQ_MASK (1 << 22)
#define OMAP3430ES1_ST_FAC_SHIFT 8
......
......@@ -63,28 +63,30 @@ void __init omap_ads7846_init(int bus_num, int gpio_pendown, int gpio_debounce,
struct spi_board_info *spi_bi = &ads7846_spi_board_info;
int err;
if (board_pdata && board_pdata->get_pendown_state) {
err = gpio_request_one(gpio_pendown, GPIOF_IN, "TSPenDown");
if (err) {
pr_err("Couldn't obtain gpio for TSPenDown: %d\n", err);
return;
}
gpio_export(gpio_pendown, 0);
if (gpio_debounce)
gpio_set_debounce(gpio_pendown, gpio_debounce);
err = gpio_request_one(gpio_pendown, GPIOF_IN, "TSPenDown");
if (err) {
pr_err("Couldn't obtain gpio for TSPenDown: %d\n", err);
return;
}
if (gpio_debounce)
gpio_set_debounce(gpio_pendown, gpio_debounce);
spi_bi->bus_num = bus_num;
spi_bi->irq = gpio_to_irq(gpio_pendown);
if (board_pdata) {
board_pdata->gpio_pendown = gpio_pendown;
spi_bi->platform_data = board_pdata;
if (board_pdata->get_pendown_state)
gpio_export(gpio_pendown, 0);
} else {
ads7846_config.gpio_pendown = gpio_pendown;
}
if (!board_pdata || (board_pdata && !board_pdata->get_pendown_state))
gpio_free(gpio_pendown);
spi_register_board_info(&ads7846_spi_board_info, 1);
}
#else
......
......@@ -36,8 +36,6 @@
#include "control.h"
#include "common.h"
#ifdef CONFIG_CPU_IDLE
/* Mach specific information to be recorded in the C-state driver_data */
struct omap3_idle_statedata {
u32 mpu_state;
......@@ -379,9 +377,3 @@ int __init omap3_idle_init(void)
return 0;
}
#else
int __init omap3_idle_init(void)
{
return 0;
}
#endif /* CONFIG_CPU_IDLE */
......@@ -22,8 +22,6 @@
#include "pm.h"
#include "prm.h"
#ifdef CONFIG_CPU_IDLE
/* Machine specific information */
struct omap4_idle_statedata {
u32 cpu_state;
......@@ -199,9 +197,3 @@ int __init omap4_idle_init(void)
return 0;
}
#else
int __init omap4_idle_init(void)
{
return 0;
}
#endif /* CONFIG_CPU_IDLE */
......@@ -36,6 +36,8 @@
#define AM35XX_EMAC_CNTRL_MOD_OFFSET (0x0)
#define AM35XX_EMAC_CNTRL_RAM_OFFSET (0x20000)
#define AM35XX_EMAC_MDIO_OFFSET (0x30000)
#define AM35XX_IPSS_MDIO_BASE (AM35XX_IPSS_EMAC_BASE + \
AM35XX_EMAC_MDIO_OFFSET)
#define AM35XX_EMAC_CNTRL_RAM_SIZE (0x2000)
#define AM35XX_EMAC_RAM_ADDR (AM3517_EMAC_BASE + \
AM3517_EMAC_CNTRL_RAM_OFFSET)
......
......@@ -262,7 +262,7 @@ int __init omap_intc_of_init(struct device_node *node,
struct device_node *parent)
{
struct resource res;
u32 nr_irqs = 96;
u32 nr_irq = 96;
if (WARN_ON(!node))
return -ENODEV;
......@@ -272,10 +272,10 @@ int __init omap_intc_of_init(struct device_node *node,
return -EINVAL;
}
if (of_property_read_u32(node, "ti,intc-size", &nr_irqs))
pr_warn("unable to get intc-size, default to %d\n", nr_irqs);
if (of_property_read_u32(node, "ti,intc-size", &nr_irq))
pr_warn("unable to get intc-size, default to %d\n", nr_irq);
omap_init_irq(res.start, nr_irqs, of_node_get(node));
omap_init_irq(res.start, nr_irq, of_node_get(node));
return 0;
}
......
......@@ -83,8 +83,6 @@ static int omap2_mbox_startup(struct omap_mbox *mbox)
l = mbox_read_reg(MAILBOX_REVISION);
pr_debug("omap mailbox rev %d.%d\n", (l & 0xf0) >> 4, (l & 0x0f));
omap2_mbox_enable_irq(mbox, IRQ_RX);
return 0;
}
......
......@@ -73,19 +73,17 @@ static struct iommu_device omap4_devices[] = {
.da_end = 0xFFFFF000,
},
},
#if defined(CONFIG_MPU_TESLA_IOMMU)
{
.base = OMAP4_MMU2_BASE,
.irq = INT_44XX_DSP_MMU,
.irq = OMAP44XX_IRQ_TESLA_MMU,
.pdata = {
.name = "tesla",
.nr_tlb_entries = 32,
.clk_name = "tesla_ick",
.clk_name = "dsp_fck",
.da_start = 0x0,
.da_end = 0xFFFFF000,
},
},
#endif
};
#define NR_OMAP4_IOMMU_DEVICES ARRAY_SIZE(omap4_devices)
static struct platform_device *omap4_iommu_pdev[NR_OMAP4_IOMMU_DEVICES];
......
......@@ -527,11 +527,27 @@ static struct omap_hwmod omap36xx_uart4_hwmod = {
static struct omap_hwmod_irq_info am35xx_uart4_mpu_irqs[] = {
{ .irq = INT_35XX_UART4_IRQ, },
{ .irq = -1 }
};
static struct omap_hwmod_dma_info am35xx_uart4_sdma_reqs[] = {
{ .name = "rx", .dma_req = AM35XX_DMA_UART4_RX, },
{ .name = "tx", .dma_req = AM35XX_DMA_UART4_TX, },
{ .dma_req = -1 }
};
/*
* XXX AM35xx UART4 cannot complete its softreset without uart1_fck or
* uart2_fck being enabled. So we add uart1_fck as an optional clock,
* below, and set the HWMOD_CONTROL_OPT_CLKS_IN_RESET. This really
* should not be needed. The functional clock structure of the AM35xx
* UART4 is extremely unclear and opaque; it is unclear what the role
* of uart1/2_fck is for the UART4. Any clarification from either
* empirical testing or the AM3505/3517 hardware designers would be
* most welcome.
*/
static struct omap_hwmod_opt_clk am35xx_uart4_opt_clks[] = {
{ .role = "softreset_uart1_fck", .clk = "uart1_fck" },
};
static struct omap_hwmod am35xx_uart4_hwmod = {
......@@ -543,11 +559,14 @@ static struct omap_hwmod am35xx_uart4_hwmod = {
.omap2 = {
.module_offs = CORE_MOD,
.prcm_reg_id = 1,
.module_bit = OMAP3430_EN_UART4_SHIFT,
.module_bit = AM35XX_EN_UART4_SHIFT,
.idlest_reg_id = 1,
.idlest_idle_bit = OMAP3430_EN_UART4_SHIFT,
.idlest_idle_bit = AM35XX_ST_UART4_SHIFT,
},
},
.opt_clks = am35xx_uart4_opt_clks,
.opt_clks_cnt = ARRAY_SIZE(am35xx_uart4_opt_clks),
.flags = HWMOD_CONTROL_OPT_CLKS_IN_RESET,
.class = &omap2_uart_class,
};
......@@ -1638,25 +1657,20 @@ static struct omap_hwmod omap3xxx_usbhsotg_hwmod = {
/* usb_otg_hs */
static struct omap_hwmod_irq_info am35xx_usbhsotg_mpu_irqs[] = {
{ .name = "mc", .irq = 71 },
{ .irq = -1 }
};
static struct omap_hwmod_class am35xx_usbotg_class = {
.name = "am35xx_usbotg",
.sysc = NULL,
};
static struct omap_hwmod am35xx_usbhsotg_hwmod = {
.name = "am35x_otg_hs",
.mpu_irqs = am35xx_usbhsotg_mpu_irqs,
.main_clk = NULL,
.prcm = {
.omap2 = {
},
},
.main_clk = "hsotgusb_fck",
.class = &am35xx_usbotg_class,
.flags = HWMOD_NO_IDLEST,
};
/* MMC/SD/SDIO common */
......@@ -2097,9 +2111,10 @@ static struct omap_hwmod_ocp_if omap3xxx_usbhsotg__l3 = {
static struct omap_hwmod_ocp_if am35xx_usbhsotg__l3 = {
.master = &am35xx_usbhsotg_hwmod,
.slave = &omap3xxx_l3_main_hwmod,
.clk = "core_l3_ick",
.clk = "hsotgusb_ick",
.user = OCP_USER_MPU,
};
/* L4_CORE -> L4_WKUP interface */
static struct omap_hwmod_ocp_if omap3xxx_l4_core__l4_wkup = {
.master = &omap3xxx_l4_core_hwmod,
......@@ -2243,6 +2258,7 @@ static struct omap_hwmod_addr_space am35xx_uart4_addr_space[] = {
.pa_end = OMAP3_UART4_AM35XX_BASE + SZ_1K - 1,
.flags = ADDR_MAP_ON_INIT | ADDR_TYPE_RT,
},
{ }
};
static struct omap_hwmod_ocp_if am35xx_l4_core__uart4 = {
......@@ -2393,7 +2409,7 @@ static struct omap_hwmod_addr_space am35xx_usbhsotg_addrs[] = {
static struct omap_hwmod_ocp_if am35xx_l4_core__usbhsotg = {
.master = &omap3xxx_l4_core_hwmod,
.slave = &am35xx_usbhsotg_hwmod,
.clk = "l4_ick",
.clk = "hsotgusb_ick",
.addr = am35xx_usbhsotg_addrs,
.user = OCP_USER_MPU,
};
......@@ -3138,6 +3154,107 @@ static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__counter_32k = {
.user = OCP_USER_MPU | OCP_USER_SDMA,
};
/* am35xx has Davinci MDIO & EMAC */
static struct omap_hwmod_class am35xx_mdio_class = {
.name = "davinci_mdio",
};
static struct omap_hwmod am35xx_mdio_hwmod = {
.name = "davinci_mdio",
.class = &am35xx_mdio_class,
.flags = HWMOD_NO_IDLEST,
};
/*
* XXX Should be connected to an IPSS hwmod, not the L3 directly;
* but this will probably require some additional hwmod core support,
* so is left as a future to-do item.
*/
static struct omap_hwmod_ocp_if am35xx_mdio__l3 = {
.master = &am35xx_mdio_hwmod,
.slave = &omap3xxx_l3_main_hwmod,
.clk = "emac_fck",
.user = OCP_USER_MPU,
};
static struct omap_hwmod_addr_space am35xx_mdio_addrs[] = {
{
.pa_start = AM35XX_IPSS_MDIO_BASE,
.pa_end = AM35XX_IPSS_MDIO_BASE + SZ_4K - 1,
.flags = ADDR_TYPE_RT,
},
{ }
};
/* l4_core -> davinci mdio */
/*
* XXX Should be connected to an IPSS hwmod, not the L4_CORE directly;
* but this will probably require some additional hwmod core support,
* so is left as a future to-do item.
*/
static struct omap_hwmod_ocp_if am35xx_l4_core__mdio = {
.master = &omap3xxx_l4_core_hwmod,
.slave = &am35xx_mdio_hwmod,
.clk = "emac_fck",
.addr = am35xx_mdio_addrs,
.user = OCP_USER_MPU,
};
static struct omap_hwmod_irq_info am35xx_emac_mpu_irqs[] = {
{ .name = "rxthresh", .irq = INT_35XX_EMAC_C0_RXTHRESH_IRQ },
{ .name = "rx_pulse", .irq = INT_35XX_EMAC_C0_RX_PULSE_IRQ },
{ .name = "tx_pulse", .irq = INT_35XX_EMAC_C0_TX_PULSE_IRQ },
{ .name = "misc_pulse", .irq = INT_35XX_EMAC_C0_MISC_PULSE_IRQ },
{ .irq = -1 }
};
static struct omap_hwmod_class am35xx_emac_class = {
.name = "davinci_emac",
};
static struct omap_hwmod am35xx_emac_hwmod = {
.name = "davinci_emac",
.mpu_irqs = am35xx_emac_mpu_irqs,
.class = &am35xx_emac_class,
.flags = HWMOD_NO_IDLEST,
};
/* l3_core -> davinci emac interface */
/*
* XXX Should be connected to an IPSS hwmod, not the L3 directly;
* but this will probably require some additional hwmod core support,
* so is left as a future to-do item.
*/
static struct omap_hwmod_ocp_if am35xx_emac__l3 = {
.master = &am35xx_emac_hwmod,
.slave = &omap3xxx_l3_main_hwmod,
.clk = "emac_ick",
.user = OCP_USER_MPU,
};
static struct omap_hwmod_addr_space am35xx_emac_addrs[] = {
{
.pa_start = AM35XX_IPSS_EMAC_BASE,
.pa_end = AM35XX_IPSS_EMAC_BASE + 0x30000 - 1,
.flags = ADDR_TYPE_RT,
},
{ }
};
/* l4_core -> davinci emac */
/*
* XXX Should be connected to an IPSS hwmod, not the L4_CORE directly;
* but this will probably require some additional hwmod core support,
* so is left as a future to-do item.
*/
static struct omap_hwmod_ocp_if am35xx_l4_core__emac = {
.master = &omap3xxx_l4_core_hwmod,
.slave = &am35xx_emac_hwmod,
.clk = "emac_ick",
.addr = am35xx_emac_addrs,
.user = OCP_USER_MPU,
};
static struct omap_hwmod_ocp_if *omap3xxx_hwmod_ocp_ifs[] __initdata = {
&omap3xxx_l3_main__l4_core,
&omap3xxx_l3_main__l4_per,
......@@ -3266,6 +3383,10 @@ static struct omap_hwmod_ocp_if *am35xx_hwmod_ocp_ifs[] __initdata = {
&omap3xxx_l4_core__usb_tll_hs,
&omap3xxx_l4_core__es3plus_mmc1,
&omap3xxx_l4_core__es3plus_mmc2,
&am35xx_mdio__l3,
&am35xx_l4_core__mdio,
&am35xx_emac__l3,
&am35xx_l4_core__emac,
NULL
};
......
......@@ -53,7 +53,7 @@ int __init omap_init_opp_table(struct omap_opp_def *opp_def,
omap_table_init = 1;
/* Lets now register with OPP library */
for (i = 0; i < opp_def_size; i++) {
for (i = 0; i < opp_def_size; i++, opp_def++) {
struct omap_hwmod *oh;
struct device *dev;
......@@ -86,7 +86,6 @@ int __init omap_init_opp_table(struct omap_opp_def *opp_def,
__func__, opp_def->freq,
opp_def->hwmod_name, i, r);
}
opp_def++;
}
return 0;
......
......@@ -15,12 +15,25 @@
#include "powerdomain.h"
#ifdef CONFIG_CPU_IDLE
extern int __init omap3_idle_init(void);
extern int __init omap4_idle_init(void);
#else
static inline int omap3_idle_init(void)
{
return 0;
}
static inline int omap4_idle_init(void)
{
return 0;
}
#endif
extern void *omap3_secure_ram_storage;
extern void omap3_pm_off_mode_enable(int);
extern void omap_sram_idle(void);
extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
extern int omap3_idle_init(void);
extern int omap4_idle_init(void);
extern int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused);
extern int (*omap_pm_suspend)(void);
......
......@@ -581,10 +581,13 @@ static void __init prcm_setup_regs(void)
OMAP3430_PER_MOD, OMAP3430_PM_MPUGRPSEL);
/* Don't attach IVA interrupts */
omap2_prm_write_mod_reg(0, WKUP_MOD, OMAP3430_PM_IVAGRPSEL);
omap2_prm_write_mod_reg(0, CORE_MOD, OMAP3430_PM_IVAGRPSEL1);
omap2_prm_write_mod_reg(0, CORE_MOD, OMAP3430ES2_PM_IVAGRPSEL3);
omap2_prm_write_mod_reg(0, OMAP3430_PER_MOD, OMAP3430_PM_IVAGRPSEL);
if (omap3_has_iva()) {
omap2_prm_write_mod_reg(0, WKUP_MOD, OMAP3430_PM_IVAGRPSEL);
omap2_prm_write_mod_reg(0, CORE_MOD, OMAP3430_PM_IVAGRPSEL1);
omap2_prm_write_mod_reg(0, CORE_MOD, OMAP3430ES2_PM_IVAGRPSEL3);
omap2_prm_write_mod_reg(0, OMAP3430_PER_MOD,
OMAP3430_PM_IVAGRPSEL);
}
/* Clear any pending 'reset' flags */
omap2_prm_write_mod_reg(0xffffffff, MPU_MOD, OMAP2_RM_RSTST);
......@@ -598,7 +601,9 @@ static void __init prcm_setup_regs(void)
/* Clear any pending PRCM interrupts */
omap2_prm_write_mod_reg(0, OCP_MOD, OMAP3_PRM_IRQSTATUS_MPU_OFFSET);
omap3_iva_idle();
if (omap3_has_iva())
omap3_iva_idle();
omap3_d2d_idle();
}
......
......@@ -71,6 +71,22 @@ static struct powerdomain mpu_3xxx_pwrdm = {
.voltdm = { .name = "mpu_iva" },
};
static struct powerdomain mpu_am35x_pwrdm = {
.name = "mpu_pwrdm",
.prcm_offs = MPU_MOD,
.pwrsts = PWRSTS_ON,
.pwrsts_logic_ret = PWRSTS_ON,
.flags = PWRDM_HAS_MPU_QUIRK,
.banks = 1,
.pwrsts_mem_ret = {
[0] = PWRSTS_ON,
},
.pwrsts_mem_on = {
[0] = PWRSTS_ON,
},
.voltdm = { .name = "mpu_iva" },
};
/*
* The USBTLL Save-and-Restore mechanism is broken on
* 3430s up to ES3.0 and 3630ES1.0. Hence this feature
......@@ -120,6 +136,23 @@ static struct powerdomain core_3xxx_es3_1_pwrdm = {
.voltdm = { .name = "core" },
};
static struct powerdomain core_am35x_pwrdm = {
.name = "core_pwrdm",
.prcm_offs = CORE_MOD,
.pwrsts = PWRSTS_ON,
.pwrsts_logic_ret = PWRSTS_ON,
.banks = 2,
.pwrsts_mem_ret = {
[0] = PWRSTS_ON, /* MEM1RETSTATE */
[1] = PWRSTS_ON, /* MEM2RETSTATE */
},
.pwrsts_mem_on = {
[0] = PWRSTS_ON, /* MEM1ONSTATE */
[1] = PWRSTS_ON, /* MEM2ONSTATE */
},
.voltdm = { .name = "core" },
};
static struct powerdomain dss_pwrdm = {
.name = "dss_pwrdm",
.prcm_offs = OMAP3430_DSS_MOD,
......@@ -135,6 +168,21 @@ static struct powerdomain dss_pwrdm = {
.voltdm = { .name = "core" },
};
static struct powerdomain dss_am35x_pwrdm = {
.name = "dss_pwrdm",
.prcm_offs = OMAP3430_DSS_MOD,
.pwrsts = PWRSTS_ON,
.pwrsts_logic_ret = PWRSTS_ON,
.banks = 1,
.pwrsts_mem_ret = {
[0] = PWRSTS_ON, /* MEMRETSTATE */
},
.pwrsts_mem_on = {
[0] = PWRSTS_ON, /* MEMONSTATE */
},
.voltdm = { .name = "core" },
};
/*
* Although the 34XX TRM Rev K Table 4-371 notes that retention is a
* possible SGX powerstate, the SGX device itself does not support
......@@ -156,6 +204,21 @@ static struct powerdomain sgx_pwrdm = {
.voltdm = { .name = "core" },
};
static struct powerdomain sgx_am35x_pwrdm = {
.name = "sgx_pwrdm",
.prcm_offs = OMAP3430ES2_SGX_MOD,
.pwrsts = PWRSTS_ON,
.pwrsts_logic_ret = PWRSTS_ON,
.banks = 1,
.pwrsts_mem_ret = {
[0] = PWRSTS_ON, /* MEMRETSTATE */
},
.pwrsts_mem_on = {
[0] = PWRSTS_ON, /* MEMONSTATE */
},
.voltdm = { .name = "core" },
};
static struct powerdomain cam_pwrdm = {
.name = "cam_pwrdm",
.prcm_offs = OMAP3430_CAM_MOD,
......@@ -186,6 +249,21 @@ static struct powerdomain per_pwrdm = {
.voltdm = { .name = "core" },
};
static struct powerdomain per_am35x_pwrdm = {
.name = "per_pwrdm",
.prcm_offs = OMAP3430_PER_MOD,
.pwrsts = PWRSTS_ON,
.pwrsts_logic_ret = PWRSTS_ON,
.banks = 1,
.pwrsts_mem_ret = {
[0] = PWRSTS_ON, /* MEMRETSTATE */
},
.pwrsts_mem_on = {
[0] = PWRSTS_ON, /* MEMONSTATE */
},
.voltdm = { .name = "core" },
};
static struct powerdomain emu_pwrdm = {
.name = "emu_pwrdm",
.prcm_offs = OMAP3430_EMU_MOD,
......@@ -200,6 +278,14 @@ static struct powerdomain neon_pwrdm = {
.voltdm = { .name = "mpu_iva" },
};
static struct powerdomain neon_am35x_pwrdm = {
.name = "neon_pwrdm",
.prcm_offs = OMAP3430_NEON_MOD,
.pwrsts = PWRSTS_ON,
.pwrsts_logic_ret = PWRSTS_ON,
.voltdm = { .name = "mpu_iva" },
};
static struct powerdomain usbhost_pwrdm = {
.name = "usbhost_pwrdm",
.prcm_offs = OMAP3430ES2_USBHOST_MOD,
......@@ -293,6 +379,22 @@ static struct powerdomain *powerdomains_omap3430es3_1plus[] __initdata = {
NULL
};
static struct powerdomain *powerdomains_am35x[] __initdata = {
&wkup_omap2_pwrdm,
&mpu_am35x_pwrdm,
&neon_am35x_pwrdm,
&core_am35x_pwrdm,
&sgx_am35x_pwrdm,
&dss_am35x_pwrdm,
&per_am35x_pwrdm,
&emu_pwrdm,
&dpll1_pwrdm,
&dpll3_pwrdm,
&dpll4_pwrdm,
&dpll5_pwrdm,
NULL
};
void __init omap3xxx_powerdomains_init(void)
{
unsigned int rev;
......@@ -301,21 +403,34 @@ void __init omap3xxx_powerdomains_init(void)
return;
pwrdm_register_platform_funcs(&omap3_pwrdm_operations);
pwrdm_register_pwrdms(powerdomains_omap3430_common);
rev = omap_rev();
if (rev == OMAP3430_REV_ES1_0)
pwrdm_register_pwrdms(powerdomains_omap3430es1);
else if (rev == OMAP3430_REV_ES2_0 || rev == OMAP3430_REV_ES2_1 ||
rev == OMAP3430_REV_ES3_0 || rev == OMAP3630_REV_ES1_0)
pwrdm_register_pwrdms(powerdomains_omap3430es2_es3_0);
else if (rev == OMAP3430_REV_ES3_1 || rev == OMAP3430_REV_ES3_1_2 ||
rev == AM35XX_REV_ES1_0 || rev == AM35XX_REV_ES1_1 ||
rev == OMAP3630_REV_ES1_1 || rev == OMAP3630_REV_ES1_2)
pwrdm_register_pwrdms(powerdomains_omap3430es3_1plus);
else
WARN(1, "OMAP3 powerdomain init: unknown chip type\n");
if (rev == AM35XX_REV_ES1_0 || rev == AM35XX_REV_ES1_1) {
pwrdm_register_pwrdms(powerdomains_am35x);
} else {
pwrdm_register_pwrdms(powerdomains_omap3430_common);
switch (rev) {
case OMAP3430_REV_ES1_0:
pwrdm_register_pwrdms(powerdomains_omap3430es1);
break;
case OMAP3430_REV_ES2_0:
case OMAP3430_REV_ES2_1:
case OMAP3430_REV_ES3_0:
case OMAP3630_REV_ES1_0:
pwrdm_register_pwrdms(powerdomains_omap3430es2_es3_0);
break;
case OMAP3430_REV_ES3_1:
case OMAP3430_REV_ES3_1_2:
case OMAP3630_REV_ES1_1:
case OMAP3630_REV_ES1_2:
pwrdm_register_pwrdms(powerdomains_omap3430es3_1plus);
break;
default:
WARN(1, "OMAP3 powerdomain init: unknown chip type\n");
}
}
pwrdm_complete_init();
}
......@@ -203,8 +203,8 @@
#define OMAP3430_EN_MMC2_SHIFT 25
#define OMAP3430_EN_MMC1_MASK (1 << 24)
#define OMAP3430_EN_MMC1_SHIFT 24
#define OMAP3430_EN_UART4_MASK (1 << 23)
#define OMAP3430_EN_UART4_SHIFT 23
#define AM35XX_EN_UART4_MASK (1 << 23)
#define AM35XX_EN_UART4_SHIFT 23
#define OMAP3430_EN_MCSPI4_MASK (1 << 21)
#define OMAP3430_EN_MCSPI4_SHIFT 21
#define OMAP3430_EN_MCSPI3_MASK (1 << 20)
......
......@@ -85,7 +85,7 @@ static void omap_prcm_irq_handler(unsigned int irq, struct irq_desc *desc)
unsigned long priority_pending[OMAP_PRCM_MAX_NR_PENDING_REG];
struct irq_chip *chip = irq_desc_get_chip(desc);
unsigned int virtirq;
int nr_irqs = prcm_irq_setup->nr_regs * 32;
int nr_irq = prcm_irq_setup->nr_regs * 32;
/*
* If we are suspended, mask all interrupts from PRCM level,
......@@ -110,7 +110,7 @@ static void omap_prcm_irq_handler(unsigned int irq, struct irq_desc *desc)
prcm_irq_setup->read_pending_irqs(pending);
/* No bit set, then all IRQs are handled */
if (find_first_bit(pending, nr_irqs) >= nr_irqs)
if (find_first_bit(pending, nr_irq) >= nr_irq)
break;
omap_prcm_events_filter_priority(pending, priority_pending);
......@@ -121,11 +121,11 @@ static void omap_prcm_irq_handler(unsigned int irq, struct irq_desc *desc)
*/
/* Serve priority events first */
for_each_set_bit(virtirq, priority_pending, nr_irqs)
for_each_set_bit(virtirq, priority_pending, nr_irq)
generic_handle_irq(prcm_irq_setup->base_irq + virtirq);
/* Serve normal events next */
for_each_set_bit(virtirq, pending, nr_irqs)
for_each_set_bit(virtirq, pending, nr_irq)
generic_handle_irq(prcm_irq_setup->base_irq + virtirq);
}
if (chip->irq_ack)
......
......@@ -49,6 +49,7 @@ static struct i2c_board_info __initdata omap4_i2c1_board_info[] = {
},
};
#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
static int twl_set_voltage(void *data, int target_uV)
{
struct voltagedomain *voltdm = (struct voltagedomain *)data;
......@@ -60,6 +61,7 @@ static int twl_get_voltage(void *data)
struct voltagedomain *voltdm = (struct voltagedomain *)data;
return voltdm_get_voltage(voltdm);
}
#endif
void __init omap_pmic_init(int bus, u32 clkrate,
const char *pmic_type, int pmic_irq,
......@@ -213,10 +215,6 @@ static struct twl_regulator_driver_data omap3_vdd2_drvdata = {
void __init omap3_pmic_get_config(struct twl4030_platform_data *pmic_data,
u32 pdata_flags, u32 regulators_flags)
{
if (!pmic_data->irq_base)
pmic_data->irq_base = TWL4030_IRQ_BASE;
if (!pmic_data->irq_end)
pmic_data->irq_end = TWL4030_IRQ_END;
if (!pmic_data->vdd1) {
omap3_vdd1.driver_data = &omap3_vdd1_drvdata;
omap3_vdd1_drvdata.data = voltdm_lookup("mpu_iva");
......@@ -481,11 +479,6 @@ static struct regulator_init_data omap4_v2v1_idata = {
void __init omap4_pmic_get_config(struct twl4030_platform_data *pmic_data,
u32 pdata_flags, u32 regulators_flags)
{
if (!pmic_data->irq_base)
pmic_data->irq_base = TWL6030_IRQ_BASE;
if (!pmic_data->irq_end)
pmic_data->irq_end = TWL6030_IRQ_END;
if (!pmic_data->vdd1) {
omap4_vdd1.driver_data = &omap4_vdd1_drvdata;
omap4_vdd1_drvdata.data = voltdm_lookup("mpu");
......
obj-y += devices.o gpio.o irq.o timer.o
obj-y += devices.o gpio.o irq.o timer.o restart.o
obj-$(CONFIG_VTWM_VERSION_VT8500) += devices-vt8500.o
obj-$(CONFIG_VTWM_VERSION_WM8505) += devices-wm8505.o
......
......@@ -23,6 +23,7 @@
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <mach/restart.h>
#include "devices.h"
......@@ -62,6 +63,7 @@ void __init bv07_init(void)
else
printk(KERN_ERR "PMC Hibernation register could not be remapped, not enabling power off!\n");
wmt_setup_restart();
vt8500_set_resources();
platform_add_devices(devices, ARRAY_SIZE(devices));
vt8500_gpio_init();
......@@ -69,6 +71,7 @@ void __init bv07_init(void)
MACHINE_START(BV07, "Benign BV07 Mini Netbook")
.atag_offset = 0x100,
.restart = wmt_restart,
.reserve = vt8500_reserve_mem,
.map_io = vt8500_map_io,
.init_irq = vt8500_init_irq,
......
/* linux/arch/arm/mach-vt8500/restart.h
*
* Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
void wmt_setup_restart(void);
void wmt_restart(char mode, const char *cmd);
/*
* arch/arm/mach-vt8500/include/mach/system.h
*
*/
#include <asm/io.h>
/* PM Software Reset request register */
#define VT8500_PMSR_VIRT 0xf8130060
static inline void arch_reset(char mode, const char *cmd)
{
writel(1, VT8500_PMSR_VIRT);
}
/* linux/arch/arm/mach-vt8500/restart.c
*
* Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*/
#include <asm/io.h>
#include <linux/of.h>
#include <linux/of_address.h>
#define LEGACY_PMC_BASE 0xD8130000
#define WMT_PRIZM_PMSR_REG 0x60
static void __iomem *pmc_base;
void wmt_setup_restart(void)
{
struct device_node *np;
/*
* Check if Power Mgmt Controller node is present in device tree. If no
* device tree node, use the legacy PMSR value (valid for all current
* SoCs).
*/
np = of_find_compatible_node(NULL, NULL, "wmt,prizm-pmc");
if (np) {
pmc_base = of_iomap(np, 0);
if (!pmc_base)
pr_err("%s:of_iomap(pmc) failed\n", __func__);
of_node_put(np);
} else {
pmc_base = ioremap(LEGACY_PMC_BASE, 0x1000);
if (!pmc_base) {
pr_err("%s:ioremap(rstc) failed\n", __func__);
return;
}
}
}
void wmt_restart(char mode, const char *cmd)
{
if (pmc_base)
writel(1, pmc_base + WMT_PRIZM_PMSR_REG);
}
......@@ -23,6 +23,7 @@
#include <asm/mach-types.h>
#include <asm/mach/arch.h>
#include <mach/restart.h>
#include "devices.h"
......@@ -61,7 +62,7 @@ void __init wm8505_7in_init(void)
pm_power_off = &vt8500_power_off;
else
printk(KERN_ERR "PMC Hibernation register could not be remapped, not enabling power off!\n");
wmt_setup_restart();
wm8505_set_resources();
platform_add_devices(devices, ARRAY_SIZE(devices));
vt8500_gpio_init();
......@@ -69,6 +70,7 @@ void __init wm8505_7in_init(void)
MACHINE_START(WM8505_7IN_NETBOOK, "WM8505 7-inch generic netbook")
.atag_offset = 0x100,
.restart = wmt_restart,
.reserve = wm8505_reserve_mem,
.map_io = wm8505_map_io,
.init_irq = wm8505_init_irq,
......
......@@ -238,9 +238,7 @@ IS_AM_SUBCLASS(335x, 0x335)
/*
* Macros to detect individual cpu types.
* These are only rarely needed.
* cpu_is_omap330(): True for OMAP330
* cpu_is_omap730(): True for OMAP730
* cpu_is_omap850(): True for OMAP850
* cpu_is_omap310(): True for OMAP310
* cpu_is_omap1510(): True for OMAP1510
* cpu_is_omap1610(): True for OMAP1610
* cpu_is_omap1611(): True for OMAP1611
......@@ -262,8 +260,6 @@ static inline int is_omap ##type (void) \
}
IS_OMAP_TYPE(310, 0x0310)
IS_OMAP_TYPE(730, 0x0730)
IS_OMAP_TYPE(850, 0x0850)
IS_OMAP_TYPE(1510, 0x1510)
IS_OMAP_TYPE(1610, 0x1610)
IS_OMAP_TYPE(1611, 0x1611)
......@@ -277,8 +273,6 @@ IS_OMAP_TYPE(2430, 0x2430)
IS_OMAP_TYPE(3430, 0x3430)
#define cpu_is_omap310() 0
#define cpu_is_omap730() 0
#define cpu_is_omap850() 0
#define cpu_is_omap1510() 0
#define cpu_is_omap1610() 0
#define cpu_is_omap5912() 0
......@@ -294,19 +288,9 @@ IS_OMAP_TYPE(3430, 0x3430)
/*
* Whether we have MULTI_OMAP1 or not, we still need to distinguish
* between 730 vs 850, 330 vs. 1510 and 1611B/5912 vs. 1710.
* between 310 vs. 1510 and 1611B/5912 vs. 1710.
*/
#if defined(CONFIG_ARCH_OMAP730)
# undef cpu_is_omap730
# define cpu_is_omap730() is_omap730()
#endif
#if defined(CONFIG_ARCH_OMAP850)
# undef cpu_is_omap850
# define cpu_is_omap850() is_omap850()
#endif
#if defined(CONFIG_ARCH_OMAP15XX)
# undef cpu_is_omap310
# undef cpu_is_omap1510
......
......@@ -99,7 +99,7 @@
/*
* OMAP730/850 has a slightly different config for the pin mux.
* - config regs are the OMAP7XX_IO_CONF_x regs (see omap730.h) regs and
* - config regs are the OMAP7XX_IO_CONF_x regs (see omap7xx.h) regs and
* not the FUNC_MUX_CTRL_x regs from hardware.h
* - for pull-up/down, only has one enable bit which is is in the same register
* as mux config
......
/* arch/arm/plat-omap/include/mach/omap730.h
*
* Hardware definitions for TI OMAP730 processor.
*
* Cleanup for Linux-2.6 by Dirk Behme <dirk.behme@de.bosch.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __ASM_ARCH_OMAP730_H
#define __ASM_ARCH_OMAP730_H
/*
* ----------------------------------------------------------------------------
* Base addresses
* ----------------------------------------------------------------------------
*/
/* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */
#define OMAP730_DSP_BASE 0xE0000000
#define OMAP730_DSP_SIZE 0x50000
#define OMAP730_DSP_START 0xE0000000
#define OMAP730_DSPREG_BASE 0xE1000000
#define OMAP730_DSPREG_SIZE SZ_128K
#define OMAP730_DSPREG_START 0xE1000000
/*
* ----------------------------------------------------------------------------
* OMAP730 specific configuration registers
* ----------------------------------------------------------------------------
*/
#define OMAP730_CONFIG_BASE 0xfffe1000
#define OMAP730_IO_CONF_0 0xfffe1070
#define OMAP730_IO_CONF_1 0xfffe1074
#define OMAP730_IO_CONF_2 0xfffe1078
#define OMAP730_IO_CONF_3 0xfffe107c
#define OMAP730_IO_CONF_4 0xfffe1080
#define OMAP730_IO_CONF_5 0xfffe1084
#define OMAP730_IO_CONF_6 0xfffe1088
#define OMAP730_IO_CONF_7 0xfffe108c
#define OMAP730_IO_CONF_8 0xfffe1090
#define OMAP730_IO_CONF_9 0xfffe1094
#define OMAP730_IO_CONF_10 0xfffe1098
#define OMAP730_IO_CONF_11 0xfffe109c
#define OMAP730_IO_CONF_12 0xfffe10a0
#define OMAP730_IO_CONF_13 0xfffe10a4
#define OMAP730_MODE_1 0xfffe1010
#define OMAP730_MODE_2 0xfffe1014
/* CSMI specials: in terms of base + offset */
#define OMAP730_MODE2_OFFSET 0x14
/*
* ----------------------------------------------------------------------------
* OMAP730 traffic controller configuration registers
* ----------------------------------------------------------------------------
*/
#define OMAP730_FLASH_CFG_0 0xfffecc10
#define OMAP730_FLASH_ACFG_0 0xfffecc50
#define OMAP730_FLASH_CFG_1 0xfffecc14
#define OMAP730_FLASH_ACFG_1 0xfffecc54
/*
* ----------------------------------------------------------------------------
* OMAP730 DSP control registers
* ----------------------------------------------------------------------------
*/
#define OMAP730_ICR_BASE 0xfffbb800
#define OMAP730_DSP_M_CTL 0xfffbb804
#define OMAP730_DSP_MMU_BASE 0xfffed200
/*
* ----------------------------------------------------------------------------
* OMAP730 PCC_UPLD configuration registers
* ----------------------------------------------------------------------------
*/
#define OMAP730_PCC_UPLD_CTRL_BASE (0xfffe0900)
#define OMAP730_PCC_UPLD_CTRL (OMAP730_PCC_UPLD_CTRL_BASE + 0x00)
#endif /* __ASM_ARCH_OMAP730_H */
/* arch/arm/plat-omap/include/mach/omap850.h
*
* Hardware definitions for TI OMAP850 processor.
*
* Derived from omap730.h by Zebediah C. McClure <zmc@lurian.net>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __ASM_ARCH_OMAP850_H
#define __ASM_ARCH_OMAP850_H
/*
* ----------------------------------------------------------------------------
* Base addresses
* ----------------------------------------------------------------------------
*/
/* Syntax: XX_BASE = Virtual base address, XX_START = Physical base address */
#define OMAP850_DSP_BASE 0xE0000000
#define OMAP850_DSP_SIZE 0x50000
#define OMAP850_DSP_START 0xE0000000
#define OMAP850_DSPREG_BASE 0xE1000000
#define OMAP850_DSPREG_SIZE SZ_128K
#define OMAP850_DSPREG_START 0xE1000000
/*
* ----------------------------------------------------------------------------
* OMAP850 specific configuration registers
* ----------------------------------------------------------------------------
*/
#define OMAP850_CONFIG_BASE 0xfffe1000
#define OMAP850_IO_CONF_0 0xfffe1070
#define OMAP850_IO_CONF_1 0xfffe1074
#define OMAP850_IO_CONF_2 0xfffe1078
#define OMAP850_IO_CONF_3 0xfffe107c
#define OMAP850_IO_CONF_4 0xfffe1080
#define OMAP850_IO_CONF_5 0xfffe1084
#define OMAP850_IO_CONF_6 0xfffe1088
#define OMAP850_IO_CONF_7 0xfffe108c
#define OMAP850_IO_CONF_8 0xfffe1090
#define OMAP850_IO_CONF_9 0xfffe1094
#define OMAP850_IO_CONF_10 0xfffe1098
#define OMAP850_IO_CONF_11 0xfffe109c
#define OMAP850_IO_CONF_12 0xfffe10a0
#define OMAP850_IO_CONF_13 0xfffe10a4
#define OMAP850_MODE_1 0xfffe1010
#define OMAP850_MODE_2 0xfffe1014
/* CSMI specials: in terms of base + offset */
#define OMAP850_MODE2_OFFSET 0x14
/*
* ----------------------------------------------------------------------------
* OMAP850 traffic controller configuration registers
* ----------------------------------------------------------------------------
*/
#define OMAP850_FLASH_CFG_0 0xfffecc10
#define OMAP850_FLASH_ACFG_0 0xfffecc50
#define OMAP850_FLASH_CFG_1 0xfffecc14
#define OMAP850_FLASH_ACFG_1 0xfffecc54
/*
* ----------------------------------------------------------------------------
* OMAP850 DSP control registers
* ----------------------------------------------------------------------------
*/
#define OMAP850_ICR_BASE 0xfffbb800
#define OMAP850_DSP_M_CTL 0xfffbb804
#define OMAP850_DSP_MMU_BASE 0xfffed200
/*
* ----------------------------------------------------------------------------
* OMAP850 PCC_UPLD configuration registers
* ----------------------------------------------------------------------------
*/
#define OMAP850_PCC_UPLD_CTRL_BASE (0xfffe0900)
#define OMAP850_PCC_UPLD_CTRL (OMAP850_PCC_UPLD_CTRL_BASE + 0x00)
#endif /* __ASM_ARCH_OMAP850_H */
......@@ -282,6 +282,8 @@ static int omap_mbox_startup(struct omap_mbox *mbox)
}
mbox->rxq = mq;
mq->mbox = mbox;
omap_mbox_enable_irq(mbox, IRQ_RX);
}
mutex_unlock(&mbox_configured_lock);
return 0;
......@@ -305,6 +307,7 @@ static void omap_mbox_fini(struct omap_mbox *mbox)
mutex_lock(&mbox_configured_lock);
if (!--mbox->use_count) {
omap_mbox_disable_irq(mbox, IRQ_RX);
free_irq(mbox->irq, mbox);
tasklet_kill(&mbox->txq->tasklet);
flush_work_sync(&mbox->rxq->work);
......@@ -338,13 +341,15 @@ struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb)
if (!mbox)
return ERR_PTR(-ENOENT);
ret = omap_mbox_startup(mbox);
if (ret)
return ERR_PTR(-ENODEV);
if (nb)
blocking_notifier_chain_register(&mbox->notifier, nb);
ret = omap_mbox_startup(mbox);
if (ret) {
blocking_notifier_chain_unregister(&mbox->notifier, nb);
return ERR_PTR(-ENODEV);
}
return mbox;
}
EXPORT_SYMBOL(omap_mbox_get);
......
......@@ -683,7 +683,6 @@ struct twl4030_audio_data {
};
struct twl4030_platform_data {
unsigned irq_base, irq_end;
struct twl4030_clock_init_data *clock;
struct twl4030_bci_platform_data *bci;
struct twl4030_gpio_platform_data *gpio;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册