--- zzzz-none-000/linux-3.10.107/arch/arm/mach-mxs/mach-mxs.c 2017-06-27 09:49:32.000000000 +0000 +++ scorpion-7490-727/linux-3.10.107/arch/arm/mach-mxs/mach-mxs.c 2021-02-04 17:41:59.000000000 +0000 @@ -13,19 +13,18 @@ #include #include #include -#include -#include #include #include #include #include -#include #include +#include #include #include #include #include #include +#include #include #include #include @@ -39,12 +38,30 @@ #define MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0 0x2 #define MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR1 0x3 +#define HW_DIGCTL_CHIPID 0x310 +#define HW_DIGCTL_CHIPID_MASK (0xffff << 16) +#define HW_DIGCTL_REV_MASK 0xff +#define HW_DIGCTL_CHIPID_MX23 (0x3780 << 16) +#define HW_DIGCTL_CHIPID_MX28 (0x2800 << 16) + +#define MXS_CHIP_REVISION_1_0 0x10 +#define MXS_CHIP_REVISION_1_1 0x11 +#define MXS_CHIP_REVISION_1_2 0x12 +#define MXS_CHIP_REVISION_1_3 0x13 +#define MXS_CHIP_REVISION_1_4 0x14 +#define MXS_CHIP_REV_UNKNOWN 0xff + #define MXS_GPIO_NR(bank, nr) ((bank) * 32 + (nr)) #define MXS_SET_ADDR 0x4 #define MXS_CLR_ADDR 0x8 #define MXS_TOG_ADDR 0xc +static u32 chipid; +static u32 socid; + +static void __iomem *reset_addr; + static inline void __mxs_setl(u32 mask, void __iomem *reg) { __raw_writel(mask, reg + MXS_SET_ADDR); @@ -60,41 +77,6 @@ __raw_writel(mask, reg + MXS_TOG_ADDR); } -/* - * MX28EVK_FLEXCAN_SWITCH is shared between both flexcan controllers - */ -#define MX28EVK_FLEXCAN_SWITCH MXS_GPIO_NR(2, 13) - -static int flexcan0_en, flexcan1_en; - -static void mx28evk_flexcan_switch(void) -{ - if (flexcan0_en || flexcan1_en) - gpio_set_value(MX28EVK_FLEXCAN_SWITCH, 1); - else - gpio_set_value(MX28EVK_FLEXCAN_SWITCH, 0); -} - -static void mx28evk_flexcan0_switch(int enable) -{ - flexcan0_en = enable; - mx28evk_flexcan_switch(); -} - -static void mx28evk_flexcan1_switch(int enable) -{ - flexcan1_en = enable; - mx28evk_flexcan_switch(); -} - -static struct flexcan_platform_data flexcan_pdata[2]; - -static struct of_dev_auxdata mxs_auxdata_lookup[] __initdata = { - OF_DEV_AUXDATA("fsl,imx28-flexcan", 0x80032000, NULL, &flexcan_pdata[0]), - OF_DEV_AUXDATA("fsl,imx28-flexcan", 0x80034000, NULL, &flexcan_pdata[1]), - { /* sentinel */ } -}; - #define OCOTP_WORD_OFFSET 0x20 #define OCOTP_WORD_COUNT 0x20 @@ -175,6 +157,8 @@ OUI_FSL, OUI_DENX, OUI_CRYSTALFONTZ, + OUI_I2SE, + OUI_ARMADEUS, }; static void __init update_fec_mac_prop(enum mac_oui oui) @@ -229,6 +213,16 @@ macaddr[1] = 0xb9; macaddr[2] = 0xe1; break; + case OUI_I2SE: + macaddr[0] = 0x00; + macaddr[1] = 0x01; + macaddr[2] = 0x87; + break; + case OUI_ARMADEUS: + macaddr[0] = 0x00; + macaddr[1] = 0x1e; + macaddr[2] = 0xac; + break; } val = ocotp[i]; macaddr[3] = (val >> 16) & 0xff; @@ -254,13 +248,9 @@ mxs_saif_clkmux_select(MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0); } -static void __init imx28_evk_post_init(void) +static void __init imx28_apf28_init(void) { - if (!gpio_request_one(MX28EVK_FLEXCAN_SWITCH, GPIOF_DIR_OUT, - "flexcan-switch")) { - flexcan_pdata[0].transceiver_switch = mx28evk_flexcan0_switch; - flexcan_pdata[1].transceiver_switch = mx28evk_flexcan1_switch; - } + update_fec_mac_prop(OUI_ARMADEUS); } static int apx4devkit_phy_fixup(struct phy_device *phy) @@ -292,7 +282,7 @@ #define TX28_FEC_PHY_RESET MXS_GPIO_NR(4, 13) #define TX28_FEC_nINT MXS_GPIO_NR(4, 5) -static const struct gpio tx28_gpios[] __initconst = { +static const struct gpio const tx28_gpios[] __initconst = { { ENET0_MDC__GPIO_4_0, GPIOF_OUT_INIT_LOW, "GPIO_4_0" }, { ENET0_MDIO__GPIO_4_1, GPIOF_OUT_INIT_LOW, "GPIO_4_1" }, { ENET0_RX_EN__GPIO_4_2, GPIOF_OUT_INIT_LOW, "GPIO_4_2" }, @@ -352,92 +342,200 @@ pinctrl_put(pctl); } -static void __init cfa10049_init(void) +static void __init crystalfontz_init(void) { update_fec_mac_prop(OUI_CRYSTALFONTZ); } -static void __init cfa10037_init(void) +static void __init duckbill_init(void) { - update_fec_mac_prop(OUI_CRYSTALFONTZ); + update_fec_mac_prop(OUI_I2SE); } -static void __init mxs_machine_init(void) +static void __init m28cu3_init(void) { - if (of_machine_is_compatible("fsl,imx28-evk")) - imx28_evk_init(); - else if (of_machine_is_compatible("bluegiga,apx4devkit")) - apx4devkit_init(); - else if (of_machine_is_compatible("crystalfontz,cfa10037")) - cfa10037_init(); - else if (of_machine_is_compatible("crystalfontz,cfa10049")) - cfa10049_init(); + update_fec_mac_prop(OUI_DENX); +} - of_platform_populate(NULL, of_default_bus_match_table, - mxs_auxdata_lookup, NULL); +static const char __init *mxs_get_soc_id(void) +{ + struct device_node *np; + void __iomem *digctl_base; - if (of_machine_is_compatible("karo,tx28")) - tx28_post_init(); + np = of_find_compatible_node(NULL, NULL, "fsl,imx23-digctl"); + digctl_base = of_iomap(np, 0); + WARN_ON(!digctl_base); + + chipid = readl(digctl_base + HW_DIGCTL_CHIPID); + socid = chipid & HW_DIGCTL_CHIPID_MASK; + + iounmap(digctl_base); + of_node_put(np); + + switch (socid) { + case HW_DIGCTL_CHIPID_MX23: + return "i.MX23"; + case HW_DIGCTL_CHIPID_MX28: + return "i.MX28"; + default: + return "Unknown"; + } +} - if (of_machine_is_compatible("fsl,imx28-evk")) - imx28_evk_post_init(); +static u32 __init mxs_get_cpu_rev(void) +{ + u32 rev = chipid & HW_DIGCTL_REV_MASK; + + switch (socid) { + case HW_DIGCTL_CHIPID_MX23: + switch (rev) { + case 0x0: + return MXS_CHIP_REVISION_1_0; + case 0x1: + return MXS_CHIP_REVISION_1_1; + case 0x2: + return MXS_CHIP_REVISION_1_2; + case 0x3: + return MXS_CHIP_REVISION_1_3; + case 0x4: + return MXS_CHIP_REVISION_1_4; + default: + return MXS_CHIP_REV_UNKNOWN; + } + case HW_DIGCTL_CHIPID_MX28: + switch (rev) { + case 0x0: + return MXS_CHIP_REVISION_1_1; + case 0x1: + return MXS_CHIP_REVISION_1_2; + default: + return MXS_CHIP_REV_UNKNOWN; + } + default: + return MXS_CHIP_REV_UNKNOWN; + } +} + +static const char __init *mxs_get_revision(void) +{ + u32 rev = mxs_get_cpu_rev(); + + if (rev != MXS_CHIP_REV_UNKNOWN) + return kasprintf(GFP_KERNEL, "%d.%d", (rev >> 4) & 0xf, + rev & 0xf); + else + return kasprintf(GFP_KERNEL, "%s", "Unknown"); } #define MX23_CLKCTRL_RESET_OFFSET 0x120 #define MX28_CLKCTRL_RESET_OFFSET 0x1e0 -#define MXS_CLKCTRL_RESET_CHIP (1 << 1) -/* - * Reset the system. It is called by machine_restart(). - */ -static void mxs_restart(char mode, const char *cmd) +static int __init mxs_restart_init(void) { struct device_node *np; - void __iomem *reset_addr; np = of_find_compatible_node(NULL, NULL, "fsl,clkctrl"); reset_addr = of_iomap(np, 0); if (!reset_addr) - goto soft; + return -ENODEV; if (of_device_is_compatible(np, "fsl,imx23-clkctrl")) reset_addr += MX23_CLKCTRL_RESET_OFFSET; else reset_addr += MX28_CLKCTRL_RESET_OFFSET; + of_node_put(np); + + return 0; +} + +static void __init eukrea_mbmx283lc_init(void) +{ + mxs_saif_clkmux_select(MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0); +} + +static void __init mxs_machine_init(void) +{ + struct device_node *root; + struct device *parent; + struct soc_device *soc_dev; + struct soc_device_attribute *soc_dev_attr; + int ret; - /* reset the chip */ - __mxs_setl(MXS_CLKCTRL_RESET_CHIP, reset_addr); + soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); + if (!soc_dev_attr) + return; - pr_err("Failed to assert the chip reset\n"); + root = of_find_node_by_path("/"); + ret = of_property_read_string(root, "model", &soc_dev_attr->machine); + if (ret) + return; - /* Delay to allow the serial port to show the message */ - mdelay(50); + soc_dev_attr->family = "Freescale MXS Family"; + soc_dev_attr->soc_id = mxs_get_soc_id(); + soc_dev_attr->revision = mxs_get_revision(); + + soc_dev = soc_device_register(soc_dev_attr); + if (IS_ERR(soc_dev)) { + kfree(soc_dev_attr->revision); + kfree(soc_dev_attr); + return; + } -soft: - /* We'll take a jump through zero as a poor second */ - soft_restart(0); + parent = soc_device_to_device(soc_dev); + + if (of_machine_is_compatible("fsl,imx28-evk")) + imx28_evk_init(); + if (of_machine_is_compatible("armadeus,imx28-apf28")) + imx28_apf28_init(); + else if (of_machine_is_compatible("bluegiga,apx4devkit")) + apx4devkit_init(); + else if (of_machine_is_compatible("crystalfontz,cfa10036")) + crystalfontz_init(); + else if (of_machine_is_compatible("eukrea,mbmx283lc")) + eukrea_mbmx283lc_init(); + else if (of_machine_is_compatible("i2se,duckbill")) + duckbill_init(); + else if (of_machine_is_compatible("msr,m28cu3")) + m28cu3_init(); + + of_platform_populate(NULL, of_default_bus_match_table, + NULL, parent); + + mxs_restart_init(); + + if (of_machine_is_compatible("karo,tx28")) + tx28_post_init(); } -static void __init mxs_timer_init(void) +#define MXS_CLKCTRL_RESET_CHIP (1 << 1) + +/* + * Reset the system. It is called by machine_restart(). + */ +static void mxs_restart(enum reboot_mode mode, const char *cmd) { - if (of_machine_is_compatible("fsl,imx23")) - mx23_clocks_init(); - else - mx28_clocks_init(); - clocksource_of_init(); + if (reset_addr) { + /* reset the chip */ + __mxs_setl(MXS_CLKCTRL_RESET_CHIP, reset_addr); + + pr_err("Failed to assert the chip reset\n"); + + /* Delay to allow the serial port to show the message */ + mdelay(50); + } + + /* We'll take a jump through zero as a poor second */ + soft_restart(0); } -static const char *mxs_dt_compat[] __initdata = { +static const char *const mxs_dt_compat[] __initconst = { "fsl,imx28", "fsl,imx23", NULL, }; DT_MACHINE_START(MXS, "Freescale MXS (Device Tree)") - .map_io = debug_ll_io_init, - .init_irq = irqchip_init, .handle_irq = icoll_handle_irq, - .init_time = mxs_timer_init, .init_machine = mxs_machine_init, .init_late = mxs_pm_init, .dt_compat = mxs_dt_compat,