| /* |
| * Copyright (C) 2015-2016 Freescale Semiconductor, Inc. |
| * |
| * The code contained herein is licensed under the GNU General Public |
| * License. You may obtain a copy of the GNU General Public License |
| * Version 2 or later at the following locations: |
| * |
| * http://www.opensource.org/licenses/gpl-license.html |
| * http://www.gnu.org/copyleft/gpl.html |
| */ |
| #include <linux/io.h> |
| #include <linux/of.h> |
| #include <linux/of_address.h> |
| #include <linux/of_net.h> |
| #include <linux/slab.h> |
| |
| #include "hardware.h" |
| |
| unsigned long iram_tlb_base_addr; |
| unsigned long iram_tlb_phys_addr; |
| |
| unsigned long save_ttbr1(void) |
| { |
| unsigned long lttbr1; |
| asm volatile( |
| ".align 4\n" |
| "mrc p15, 0, %0, c2, c0, 1\n" |
| : "=r" (lttbr1) |
| ); |
| return lttbr1; |
| } |
| |
| void restore_ttbr1(unsigned long ttbr1) |
| { |
| asm volatile( |
| ".align 4\n" |
| "mcr p15, 0, %0, c2, c0, 1\n" |
| : : "r" (ttbr1) |
| ); |
| } |
| |
| #define OCOTP_MAC_OFF (cpu_is_imx7d() ? 0x640 : 0x620) |
| #define OCOTP_MACn(n) (OCOTP_MAC_OFF + (n) * 0x10) |
| void __init imx6_enet_mac_init(const char *enet_compat, const char *ocotp_compat) |
| { |
| struct device_node *ocotp_np, *enet_np, *from = NULL; |
| void __iomem *base; |
| struct property *newmac; |
| u32 macaddr_low; |
| u32 macaddr_high = 0; |
| u32 macaddr1_high = 0; |
| u8 *macaddr; |
| int i, id; |
| |
| for (i = 0; i < 2; i++) { |
| enet_np = of_find_compatible_node(from, NULL, enet_compat); |
| if (!enet_np) |
| return; |
| |
| from = enet_np; |
| |
| if (of_get_mac_address(enet_np)) |
| goto put_enet_node; |
| |
| id = of_alias_get_id(enet_np, "ethernet"); |
| if (id < 0) |
| id = i; |
| |
| ocotp_np = of_find_compatible_node(NULL, NULL, ocotp_compat); |
| if (!ocotp_np) { |
| pr_warn("failed to find ocotp node\n"); |
| goto put_enet_node; |
| } |
| |
| base = of_iomap(ocotp_np, 0); |
| if (!base) { |
| pr_warn("failed to map ocotp\n"); |
| goto put_ocotp_node; |
| } |
| |
| macaddr_low = readl_relaxed(base + OCOTP_MACn(1)); |
| if (id) |
| macaddr1_high = readl_relaxed(base + OCOTP_MACn(2)); |
| else |
| macaddr_high = readl_relaxed(base + OCOTP_MACn(0)); |
| |
| newmac = kzalloc(sizeof(*newmac) + 6, GFP_KERNEL); |
| if (!newmac) |
| goto put_ocotp_node; |
| |
| newmac->value = newmac + 1; |
| newmac->length = 6; |
| newmac->name = kstrdup("local-mac-address", GFP_KERNEL); |
| if (!newmac->name) { |
| kfree(newmac); |
| goto put_ocotp_node; |
| } |
| |
| macaddr = newmac->value; |
| if (id) { |
| macaddr[5] = (macaddr_low >> 16) & 0xff; |
| macaddr[4] = (macaddr_low >> 24) & 0xff; |
| macaddr[3] = macaddr1_high & 0xff; |
| macaddr[2] = (macaddr1_high >> 8) & 0xff; |
| macaddr[1] = (macaddr1_high >> 16) & 0xff; |
| macaddr[0] = (macaddr1_high >> 24) & 0xff; |
| } else { |
| macaddr[5] = macaddr_high & 0xff; |
| macaddr[4] = (macaddr_high >> 8) & 0xff; |
| macaddr[3] = (macaddr_high >> 16) & 0xff; |
| macaddr[2] = (macaddr_high >> 24) & 0xff; |
| macaddr[1] = macaddr_low & 0xff; |
| macaddr[0] = (macaddr_low >> 8) & 0xff; |
| } |
| |
| of_update_property(enet_np, newmac); |
| |
| put_ocotp_node: |
| of_node_put(ocotp_np); |
| put_enet_node: |
| of_node_put(enet_np); |
| } |
| } |
| |
| #ifndef CONFIG_HAVE_IMX_GPC |
| int imx_gpc_mf_request_on(unsigned int irq, unsigned int on) { return 0; } |
| EXPORT_SYMBOL_GPL(imx_gpc_mf_request_on); |
| #endif |
| |
| #if !defined(CONFIG_SOC_IMX6SL) |
| u32 imx6_lpddr2_freq_change_start, imx6_lpddr2_freq_change_end; |
| void mx6_lpddr2_freq_change(u32 freq, int bus_freq_mode) {} |
| #endif |
| |
| #if !defined(CONFIG_SOC_IMX6SLL) |
| void imx6sll_lpddr2_freq_change(u32 freq, int bus_freq_mode) {} |
| #endif |
| |
| #if !defined(CONFIG_SOC_IMX6SX) && !defined(CONFIG_SOC_IMX6UL) |
| u32 imx6_up_ddr3_freq_change_start, imx6_up_ddr3_freq_change_end; |
| struct imx6_busfreq_info { |
| } __aligned(8); |
| void imx6_up_ddr3_freq_change(struct imx6_busfreq_info *busfreq_info) {} |
| void imx6_up_lpddr2_freq_change(u32 freq, int bus_freq_mode) {} |
| #endif |
| |
| #if !defined(CONFIG_SOC_IMX6ULL) |
| u32 mx6ull_lpm_wfi_start, mx6ull_lpm_wfi_end; |
| void imx6ull_low_power_idle(void) {} |
| #endif |
| |
| #if !defined(CONFIG_SOC_IMX6Q) |
| u32 mx6_ddr3_freq_change_start, mx6_ddr3_freq_change_end; |
| u32 mx6q_lpddr2_freq_change_start, mx6q_lpddr2_freq_change_end; |
| u32 wfe_smp_freq_change_start, wfe_smp_freq_change_end; |
| void mx6_ddr3_freq_change(u32 freq, void *ddr_settings, |
| bool dll_mode, void *iomux_offsets) {} |
| void mx6q_lpddr2_freq_change(u32 freq, void *ddr_settings) {} |
| void wfe_smp_freq_change(u32 cpuid, u32 *ddr_freq_change_done) {} |
| #endif |
| |
| #if !defined(CONFIG_SOC_IMX7D) |
| void imx7_smp_wfe(u32 cpuid, u32 ocram_base) {} |
| void imx7d_ddr3_freq_change(u32 freq) {} |
| #endif |
| |