ramips: add v4.9 support
NAND support is missing Signed-off-by: John Crispin <john@phrozen.org>
This commit is contained in:
		| @@ -0,0 +1,62 @@ | ||||
| config NET_VENDOR_MEDIATEK | ||||
| 	tristate "Mediatek/Ralink ethernet driver" | ||||
| 	depends on RALINK | ||||
| 	help | ||||
| 	  This driver supports the ethernet mac inside the Mediatek and Ralink WiSoCs | ||||
|  | ||||
| config NET_MEDIATEK_SOC | ||||
| 	def_tristate NET_VENDOR_MEDIATEK | ||||
|  | ||||
| if NET_MEDIATEK_SOC | ||||
| choice | ||||
| 	prompt "MAC type" | ||||
|  | ||||
| config NET_MEDIATEK_RT2880 | ||||
| 	bool "RT2882" | ||||
| 	depends on MIPS && SOC_RT288X | ||||
|  | ||||
| config NET_MEDIATEK_RT3050 | ||||
| 	bool "RT3050/MT7628" | ||||
| 	depends on MIPS && (SOC_RT305X || SOC_MT7620) | ||||
|  | ||||
| config NET_MEDIATEK_RT3883 | ||||
| 	bool "RT3883" | ||||
| 	depends on MIPS && SOC_RT3883 | ||||
|  | ||||
| config NET_MEDIATEK_MT7620 | ||||
| 	bool "MT7620" | ||||
| 	depends on MIPS && SOC_MT7620 | ||||
|  | ||||
| config NET_MEDIATEK_MT7621 | ||||
| 	bool "MT7621" | ||||
| 	depends on MIPS && SOC_MT7621 | ||||
|  | ||||
| endchoice | ||||
|  | ||||
| config NET_MEDIATEK_MDIO | ||||
| 	def_bool NET_MEDIATEK_SOC | ||||
| 	depends on (NET_MEDIATEK_RT2880 || NET_MEDIATEK_RT3883 || NET_MEDIATEK_MT7620 || NET_MEDIATEK_MT7621) | ||||
| 	select PHYLIB | ||||
|  | ||||
| config NET_MEDIATEK_MDIO_RT2880 | ||||
| 	def_bool NET_MEDIATEK_SOC | ||||
| 	depends on (NET_MEDIATEK_RT2880 || NET_MEDIATEK_RT3883) | ||||
| 	select NET_MEDIATEK_MDIO | ||||
|  | ||||
| config NET_MEDIATEK_MDIO_MT7620 | ||||
| 	def_bool NET_MEDIATEK_SOC | ||||
| 	depends on (NET_MEDIATEK_MT7620 || NET_MEDIATEK_MT7621) | ||||
| 	select NET_MEDIATEK_MDIO | ||||
|  | ||||
| config NET_MEDIATEK_ESW_RT3050 | ||||
| 	def_tristate NET_MEDIATEK_SOC | ||||
| 	depends on NET_MEDIATEK_RT3050 | ||||
|  | ||||
| config NET_MEDIATEK_GSW_MT7620 | ||||
| 	def_tristate NET_MEDIATEK_SOC | ||||
| 	depends on NET_MEDIATEK_MT7620 | ||||
|  | ||||
| config NET_MEDIATEK_GSW_MT7621 | ||||
| 	def_tristate NET_MEDIATEK_SOC | ||||
| 	depends on NET_MEDIATEK_MT7621 | ||||
| endif | ||||
| @@ -0,0 +1,20 @@ | ||||
| # | ||||
| # Makefile for the Ralink SoCs built-in ethernet macs | ||||
| # | ||||
|  | ||||
| mtk-eth-soc-y					+= mtk_eth_soc.o ethtool.o | ||||
|  | ||||
| mtk-eth-soc-$(CONFIG_NET_MEDIATEK_MDIO)		+= mdio.o | ||||
| mtk-eth-soc-$(CONFIG_NET_MEDIATEK_MDIO_RT2880)	+= mdio_rt2880.o | ||||
| mtk-eth-soc-$(CONFIG_NET_MEDIATEK_MDIO_MT7620)	+= mdio_mt7620.o | ||||
|  | ||||
| mtk-eth-soc-$(CONFIG_NET_MEDIATEK_RT2880)	+= soc_rt2880.o | ||||
| mtk-eth-soc-$(CONFIG_NET_MEDIATEK_RT3050)	+= soc_rt3050.o | ||||
| mtk-eth-soc-$(CONFIG_NET_MEDIATEK_RT3883)	+= soc_rt3883.o | ||||
| mtk-eth-soc-$(CONFIG_NET_MEDIATEK_MT7620)	+= soc_mt7620.o | ||||
| mtk-eth-soc-$(CONFIG_NET_MEDIATEK_MT7621)	+= soc_mt7621.o | ||||
|  | ||||
| obj-$(CONFIG_NET_MEDIATEK_ESW_RT3050)		+= esw_rt3050.o | ||||
| obj-$(CONFIG_NET_MEDIATEK_GSW_MT7620)		+= gsw_mt7620.o mt7530.o | ||||
| obj-$(CONFIG_NET_MEDIATEK_GSW_MT7621)		+= gsw_mt7621.o mt7530.o | ||||
| obj-$(CONFIG_NET_MEDIATEK_SOC)			+= mtk-eth-soc.o | ||||
							
								
								
									
										1461
									
								
								target/linux/ramips/files-4.9/drivers/net/ethernet/mtk/esw_rt3050.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1461
									
								
								target/linux/ramips/files-4.9/drivers/net/ethernet/mtk/esw_rt3050.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,29 @@ | ||||
| /*   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; version 2 of the License | ||||
|  * | ||||
|  *   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. | ||||
|  * | ||||
|  *   Copyright (C) 2009-2015 John Crispin <blogic@openwrt.org> | ||||
|  *   Copyright (C) 2009-2015 Felix Fietkau <nbd@nbd.name> | ||||
|  *   Copyright (C) 2013-2015 Michael Lee <igvtee@gmail.com> | ||||
|  */ | ||||
|  | ||||
| #ifndef _RALINK_ESW_RT3052_H__ | ||||
| #define _RALINK_ESW_RT3052_H__ | ||||
|  | ||||
| #ifdef CONFIG_NET_MEDIATEK_ESW_RT3052 | ||||
|  | ||||
| int __init mtk_switch_init(void); | ||||
| void mtk_switch_exit(void); | ||||
|  | ||||
| #else | ||||
|  | ||||
| static inline int __init mtk_switch_init(void) { return 0; } | ||||
| static inline void mtk_switch_exit(void) { } | ||||
|  | ||||
| #endif | ||||
| #endif | ||||
							
								
								
									
										233
									
								
								target/linux/ramips/files-4.9/drivers/net/ethernet/mtk/ethtool.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										233
									
								
								target/linux/ramips/files-4.9/drivers/net/ethernet/mtk/ethtool.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,233 @@ | ||||
| /*   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; version 2 of the License | ||||
|  * | ||||
|  *   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. | ||||
|  * | ||||
|  *   Copyright (C) 2009-2015 John Crispin <blogic@openwrt.org> | ||||
|  *   Copyright (C) 2009-2015 Felix Fietkau <nbd@nbd.name> | ||||
|  *   Copyright (C) 2013-2015 Michael Lee <igvtee@gmail.com> | ||||
|  */ | ||||
|  | ||||
| #include "mtk_eth_soc.h" | ||||
|  | ||||
| static const char fe_gdma_str[][ETH_GSTRING_LEN] = { | ||||
| #define _FE(x...)	# x, | ||||
| FE_STAT_REG_DECLARE | ||||
| #undef _FE | ||||
| }; | ||||
|  | ||||
| static int fe_get_settings(struct net_device *dev, | ||||
| 			   struct ethtool_cmd *cmd) | ||||
| { | ||||
| 	struct fe_priv *priv = netdev_priv(dev); | ||||
| 	int err; | ||||
|  | ||||
| 	if (!priv->phy_dev) | ||||
| 		goto out_gset; | ||||
|  | ||||
| 	if (priv->phy_flags == FE_PHY_FLAG_ATTACH) { | ||||
| 		err = phy_read_status(priv->phy_dev); | ||||
| 		if (err) | ||||
| 			goto out_gset; | ||||
| 	} | ||||
|  | ||||
| 	return phy_ethtool_gset(priv->phy_dev, cmd); | ||||
|  | ||||
| out_gset: | ||||
| 	return -ENODEV; | ||||
| } | ||||
|  | ||||
| static int fe_set_settings(struct net_device *dev, | ||||
| 			   struct ethtool_cmd *cmd) | ||||
| { | ||||
| 	struct fe_priv *priv = netdev_priv(dev); | ||||
|  | ||||
| 	if (!priv->phy_dev) | ||||
| 		goto out_sset; | ||||
|  | ||||
| 	if (cmd->phy_address != priv->phy_dev->mdio.addr) { | ||||
| 		if (priv->phy->phy_node[cmd->phy_address]) { | ||||
| 			priv->phy_dev = priv->phy->phy[cmd->phy_address]; | ||||
| 			priv->phy_flags = FE_PHY_FLAG_PORT; | ||||
| 		} else if (priv->mii_bus && mdiobus_get_phy(priv->mii_bus, cmd->phy_address)) { | ||||
| 			priv->phy_dev = mdiobus_get_phy(priv->mii_bus, cmd->phy_address); | ||||
| 			priv->phy_flags = FE_PHY_FLAG_ATTACH; | ||||
| 		} else { | ||||
| 			goto out_sset; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return phy_ethtool_sset(priv->phy_dev, cmd); | ||||
|  | ||||
| out_sset: | ||||
| 	return -ENODEV; | ||||
| } | ||||
|  | ||||
| static void fe_get_drvinfo(struct net_device *dev, | ||||
| 			   struct ethtool_drvinfo *info) | ||||
| { | ||||
| 	struct fe_priv *priv = netdev_priv(dev); | ||||
| 	struct fe_soc_data *soc = priv->soc; | ||||
|  | ||||
| 	strlcpy(info->driver, priv->device->driver->name, sizeof(info->driver)); | ||||
| 	strlcpy(info->version, MTK_FE_DRV_VERSION, sizeof(info->version)); | ||||
| 	strlcpy(info->bus_info, dev_name(priv->device), sizeof(info->bus_info)); | ||||
|  | ||||
| 	if (soc->reg_table[FE_REG_FE_COUNTER_BASE]) | ||||
| 		info->n_stats = ARRAY_SIZE(fe_gdma_str); | ||||
| } | ||||
|  | ||||
| static u32 fe_get_msglevel(struct net_device *dev) | ||||
| { | ||||
| 	struct fe_priv *priv = netdev_priv(dev); | ||||
|  | ||||
| 	return priv->msg_enable; | ||||
| } | ||||
|  | ||||
| static void fe_set_msglevel(struct net_device *dev, u32 value) | ||||
| { | ||||
| 	struct fe_priv *priv = netdev_priv(dev); | ||||
|  | ||||
| 	priv->msg_enable = value; | ||||
| } | ||||
|  | ||||
| static int fe_nway_reset(struct net_device *dev) | ||||
| { | ||||
| 	struct fe_priv *priv = netdev_priv(dev); | ||||
|  | ||||
| 	if (!priv->phy_dev) | ||||
| 		goto out_nway_reset; | ||||
|  | ||||
| 	return genphy_restart_aneg(priv->phy_dev); | ||||
|  | ||||
| out_nway_reset: | ||||
| 	return -EOPNOTSUPP; | ||||
| } | ||||
|  | ||||
| static u32 fe_get_link(struct net_device *dev) | ||||
| { | ||||
| 	struct fe_priv *priv = netdev_priv(dev); | ||||
| 	int err; | ||||
|  | ||||
| 	if (!priv->phy_dev) | ||||
| 		goto out_get_link; | ||||
|  | ||||
| 	if (priv->phy_flags == FE_PHY_FLAG_ATTACH) { | ||||
| 		err = genphy_update_link(priv->phy_dev); | ||||
| 		if (err) | ||||
| 			goto out_get_link; | ||||
| 	} | ||||
|  | ||||
| 	return priv->phy_dev->link; | ||||
|  | ||||
| out_get_link: | ||||
| 	return ethtool_op_get_link(dev); | ||||
| } | ||||
|  | ||||
| static int fe_set_ringparam(struct net_device *dev, | ||||
| 			    struct ethtool_ringparam *ring) | ||||
| { | ||||
| 	struct fe_priv *priv = netdev_priv(dev); | ||||
|  | ||||
| 	if ((ring->tx_pending < 2) || | ||||
| 	    (ring->rx_pending < 2) || | ||||
| 	    (ring->rx_pending > MAX_DMA_DESC) || | ||||
| 	    (ring->tx_pending > MAX_DMA_DESC)) | ||||
| 		return -EINVAL; | ||||
|  | ||||
| 	dev->netdev_ops->ndo_stop(dev); | ||||
|  | ||||
| 	priv->tx_ring.tx_ring_size = BIT(fls(ring->tx_pending) - 1); | ||||
| 	priv->rx_ring.rx_ring_size = BIT(fls(ring->rx_pending) - 1); | ||||
|  | ||||
| 	dev->netdev_ops->ndo_open(dev); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static void fe_get_ringparam(struct net_device *dev, | ||||
| 			     struct ethtool_ringparam *ring) | ||||
| { | ||||
| 	struct fe_priv *priv = netdev_priv(dev); | ||||
|  | ||||
| 	ring->rx_max_pending = MAX_DMA_DESC; | ||||
| 	ring->tx_max_pending = MAX_DMA_DESC; | ||||
| 	ring->rx_pending = priv->rx_ring.rx_ring_size; | ||||
| 	ring->tx_pending = priv->tx_ring.tx_ring_size; | ||||
| } | ||||
|  | ||||
| static void fe_get_strings(struct net_device *dev, u32 stringset, u8 *data) | ||||
| { | ||||
| 	switch (stringset) { | ||||
| 	case ETH_SS_STATS: | ||||
| 		memcpy(data, *fe_gdma_str, sizeof(fe_gdma_str)); | ||||
| 		break; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static int fe_get_sset_count(struct net_device *dev, int sset) | ||||
| { | ||||
| 	switch (sset) { | ||||
| 	case ETH_SS_STATS: | ||||
| 		return ARRAY_SIZE(fe_gdma_str); | ||||
| 	default: | ||||
| 		return -EOPNOTSUPP; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void fe_get_ethtool_stats(struct net_device *dev, | ||||
| 				 struct ethtool_stats *stats, u64 *data) | ||||
| { | ||||
| 	struct fe_priv *priv = netdev_priv(dev); | ||||
| 	struct fe_hw_stats *hwstats = priv->hw_stats; | ||||
| 	u64 *data_src, *data_dst; | ||||
| 	unsigned int start; | ||||
| 	int i; | ||||
|  | ||||
| 	if (netif_running(dev) && netif_device_present(dev)) { | ||||
| 		if (spin_trylock(&hwstats->stats_lock)) { | ||||
| 			fe_stats_update(priv); | ||||
| 			spin_unlock(&hwstats->stats_lock); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	do { | ||||
| 		data_src = &hwstats->tx_bytes; | ||||
| 		data_dst = data; | ||||
| 		start = u64_stats_fetch_begin_irq(&hwstats->syncp); | ||||
|  | ||||
| 		for (i = 0; i < ARRAY_SIZE(fe_gdma_str); i++) | ||||
| 			*data_dst++ = *data_src++; | ||||
|  | ||||
| 	} while (u64_stats_fetch_retry_irq(&hwstats->syncp, start)); | ||||
| } | ||||
|  | ||||
| static struct ethtool_ops fe_ethtool_ops = { | ||||
| 	.get_settings		= fe_get_settings, | ||||
| 	.set_settings		= fe_set_settings, | ||||
| 	.get_drvinfo		= fe_get_drvinfo, | ||||
| 	.get_msglevel		= fe_get_msglevel, | ||||
| 	.set_msglevel		= fe_set_msglevel, | ||||
| 	.nway_reset		= fe_nway_reset, | ||||
| 	.get_link		= fe_get_link, | ||||
| 	.set_ringparam		= fe_set_ringparam, | ||||
| 	.get_ringparam		= fe_get_ringparam, | ||||
| }; | ||||
|  | ||||
| void fe_set_ethtool_ops(struct net_device *netdev) | ||||
| { | ||||
| 	struct fe_priv *priv = netdev_priv(netdev); | ||||
| 	struct fe_soc_data *soc = priv->soc; | ||||
|  | ||||
| 	if (soc->reg_table[FE_REG_FE_COUNTER_BASE]) { | ||||
| 		fe_ethtool_ops.get_strings = fe_get_strings; | ||||
| 		fe_ethtool_ops.get_sset_count = fe_get_sset_count; | ||||
| 		fe_ethtool_ops.get_ethtool_stats = fe_get_ethtool_stats; | ||||
| 	} | ||||
|  | ||||
| 	netdev->ethtool_ops = &fe_ethtool_ops; | ||||
| } | ||||
| @@ -0,0 +1,22 @@ | ||||
| /*   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; version 2 of the License | ||||
|  * | ||||
|  *   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. | ||||
|  * | ||||
|  *   Copyright (C) 2009-2015 John Crispin <blogic@openwrt.org> | ||||
|  *   Copyright (C) 2009-2015 Felix Fietkau <nbd@nbd.name> | ||||
|  *   Copyright (C) 2013-2015 Michael Lee <igvtee@gmail.com> | ||||
|  */ | ||||
|  | ||||
| #ifndef FE_ETHTOOL_H | ||||
| #define FE_ETHTOOL_H | ||||
|  | ||||
| #include <linux/ethtool.h> | ||||
|  | ||||
| void fe_set_ethtool_ops(struct net_device *netdev); | ||||
|  | ||||
| #endif /* FE_ETHTOOL_H */ | ||||
| @@ -0,0 +1,259 @@ | ||||
| /*   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; version 2 of the License | ||||
|  * | ||||
|  *   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. | ||||
|  * | ||||
|  *   Copyright (C) 2009-2015 John Crispin <blogic@openwrt.org> | ||||
|  *   Copyright (C) 2009-2015 Felix Fietkau <nbd@nbd.name> | ||||
|  *   Copyright (C) 2013-2015 Michael Lee <igvtee@gmail.com> | ||||
|  */ | ||||
|  | ||||
| #include <linux/module.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/types.h> | ||||
| #include <linux/platform_device.h> | ||||
| #include <linux/of_device.h> | ||||
| #include <linux/of_irq.h> | ||||
|  | ||||
| #include <ralink_regs.h> | ||||
|  | ||||
| #include "mtk_eth_soc.h" | ||||
| #include "gsw_mt7620.h" | ||||
|  | ||||
| void mtk_switch_w32(struct mt7620_gsw *gsw, u32 val, unsigned reg) | ||||
| { | ||||
| 	iowrite32(val, gsw->base + reg); | ||||
| } | ||||
|  | ||||
| u32 mtk_switch_r32(struct mt7620_gsw *gsw, unsigned reg) | ||||
| { | ||||
| 	return ioread32(gsw->base + reg); | ||||
| } | ||||
|  | ||||
| static irqreturn_t gsw_interrupt_mt7620(int irq, void *_priv) | ||||
| { | ||||
| 	struct fe_priv *priv = (struct fe_priv *)_priv; | ||||
| 	struct mt7620_gsw *gsw = (struct mt7620_gsw *)priv->soc->swpriv; | ||||
| 	u32 status; | ||||
| 	int i, max = (gsw->port4 == PORT4_EPHY) ? (4) : (3); | ||||
|  | ||||
| 	status = mtk_switch_r32(gsw, GSW_REG_ISR); | ||||
| 	if (status & PORT_IRQ_ST_CHG) | ||||
| 		for (i = 0; i <= max; i++) { | ||||
| 			u32 status = mtk_switch_r32(gsw, GSW_REG_PORT_STATUS(i)); | ||||
| 			int link = status & 0x1; | ||||
|  | ||||
| 			if (link != priv->link[i]) | ||||
| 				mt7620_print_link_state(priv, i, link, | ||||
| 							(status >> 2) & 3, | ||||
| 							(status & 0x2)); | ||||
|  | ||||
| 			priv->link[i] = link; | ||||
| 		} | ||||
| 	mt7620_handle_carrier(priv); | ||||
| 	mtk_switch_w32(gsw, status, GSW_REG_ISR); | ||||
|  | ||||
| 	return IRQ_HANDLED; | ||||
| } | ||||
|  | ||||
| static void mt7620_hw_init(struct mt7620_gsw *gsw, struct device_node *np) | ||||
| { | ||||
| 	u32 is_BGA = (rt_sysc_r32(0x0c) >> 16) & 1; | ||||
|  | ||||
| 	rt_sysc_w32(rt_sysc_r32(SYSC_REG_CFG1) | BIT(8), SYSC_REG_CFG1); | ||||
| 	mtk_switch_w32(gsw, mtk_switch_r32(gsw, GSW_REG_CKGCR) & ~(0x3 << 4), GSW_REG_CKGCR); | ||||
|  | ||||
| 	/* Enable MIB stats */ | ||||
| 	mtk_switch_w32(gsw, mtk_switch_r32(gsw, GSW_REG_MIB_CNT_EN) | (1 << 1), GSW_REG_MIB_CNT_EN); | ||||
|  | ||||
| 	if (of_property_read_bool(np, "mediatek,mt7530")) { | ||||
| 		u32 val; | ||||
|  | ||||
| 		/* turn off ephy and set phy base addr to 12 */ | ||||
| 		mtk_switch_w32(gsw, mtk_switch_r32(gsw, GSW_REG_GPC1) | | ||||
| 			(0x1f << 24) | (0xc << 16), | ||||
| 			GSW_REG_GPC1); | ||||
|  | ||||
| 		/* set MT7530 central align */ | ||||
| 		val = mt7530_mdio_r32(gsw, 0x7830); | ||||
| 		val &= ~BIT(0); | ||||
| 		val |= BIT(1); | ||||
| 		mt7530_mdio_w32(gsw, 0x7830, val); | ||||
|  | ||||
| 		val = mt7530_mdio_r32(gsw, 0x7a40); | ||||
| 		val &= ~BIT(30); | ||||
| 		mt7530_mdio_w32(gsw, 0x7a40, val); | ||||
|  | ||||
| 		mt7530_mdio_w32(gsw, 0x7a78, 0x855); | ||||
| 	} else { | ||||
| 		/* global page 4 */ | ||||
| 		_mt7620_mii_write(gsw, 1, 31, 0x4000); | ||||
|  | ||||
| 		_mt7620_mii_write(gsw, 1, 17, 0x7444); | ||||
| 		if (is_BGA) | ||||
| 			_mt7620_mii_write(gsw, 1, 19, 0x0114); | ||||
| 		else | ||||
| 			_mt7620_mii_write(gsw, 1, 19, 0x0117); | ||||
|  | ||||
| 		_mt7620_mii_write(gsw, 1, 22, 0x10cf); | ||||
| 		_mt7620_mii_write(gsw, 1, 25, 0x6212); | ||||
| 		_mt7620_mii_write(gsw, 1, 26, 0x0777); | ||||
| 		_mt7620_mii_write(gsw, 1, 29, 0x4000); | ||||
| 		_mt7620_mii_write(gsw, 1, 28, 0xc077); | ||||
| 		_mt7620_mii_write(gsw, 1, 24, 0x0000); | ||||
|  | ||||
| 		/* global page 3 */ | ||||
| 		_mt7620_mii_write(gsw, 1, 31, 0x3000); | ||||
| 		_mt7620_mii_write(gsw, 1, 17, 0x4838); | ||||
|  | ||||
| 		/* global page 2 */ | ||||
| 		_mt7620_mii_write(gsw, 1, 31, 0x2000); | ||||
| 		if (is_BGA) { | ||||
| 			_mt7620_mii_write(gsw, 1, 21, 0x0515); | ||||
| 			_mt7620_mii_write(gsw, 1, 22, 0x0053); | ||||
| 			_mt7620_mii_write(gsw, 1, 23, 0x00bf); | ||||
| 			_mt7620_mii_write(gsw, 1, 24, 0x0aaf); | ||||
| 			_mt7620_mii_write(gsw, 1, 25, 0x0fad); | ||||
| 			_mt7620_mii_write(gsw, 1, 26, 0x0fc1); | ||||
| 		} else { | ||||
| 			_mt7620_mii_write(gsw, 1, 21, 0x0517); | ||||
| 			_mt7620_mii_write(gsw, 1, 22, 0x0fd2); | ||||
| 			_mt7620_mii_write(gsw, 1, 23, 0x00bf); | ||||
| 			_mt7620_mii_write(gsw, 1, 24, 0x0aab); | ||||
| 			_mt7620_mii_write(gsw, 1, 25, 0x00ae); | ||||
| 			_mt7620_mii_write(gsw, 1, 26, 0x0fff); | ||||
| 		} | ||||
| 		/* global page 1 */ | ||||
| 		_mt7620_mii_write(gsw, 1, 31, 0x1000); | ||||
| 		_mt7620_mii_write(gsw, 1, 17, 0xe7f8); | ||||
| 	} | ||||
|  | ||||
| 	/* global page 0 */ | ||||
| 	_mt7620_mii_write(gsw, 1, 31, 0x8000); | ||||
| 	_mt7620_mii_write(gsw, 0, 30, 0xa000); | ||||
| 	_mt7620_mii_write(gsw, 1, 30, 0xa000); | ||||
| 	_mt7620_mii_write(gsw, 2, 30, 0xa000); | ||||
| 	_mt7620_mii_write(gsw, 3, 30, 0xa000); | ||||
|  | ||||
| 	_mt7620_mii_write(gsw, 0, 4, 0x05e1); | ||||
| 	_mt7620_mii_write(gsw, 1, 4, 0x05e1); | ||||
| 	_mt7620_mii_write(gsw, 2, 4, 0x05e1); | ||||
| 	_mt7620_mii_write(gsw, 3, 4, 0x05e1); | ||||
|  | ||||
| 	/* global page 2 */ | ||||
| 	_mt7620_mii_write(gsw, 1, 31, 0xa000); | ||||
| 	_mt7620_mii_write(gsw, 0, 16, 0x1111); | ||||
| 	_mt7620_mii_write(gsw, 1, 16, 0x1010); | ||||
| 	_mt7620_mii_write(gsw, 2, 16, 0x1515); | ||||
| 	_mt7620_mii_write(gsw, 3, 16, 0x0f0f); | ||||
|  | ||||
| 	/* CPU Port6 Force Link 1G, FC ON */ | ||||
| 	mtk_switch_w32(gsw, 0x5e33b, GSW_REG_PORT_PMCR(6)); | ||||
|  | ||||
| 	/* Set Port 6 as CPU Port */ | ||||
| 	mtk_switch_w32(gsw, 0x7f7f7fe0, 0x0010); | ||||
|  | ||||
| 	/* setup port 4 */ | ||||
| 	if (gsw->port4 == PORT4_EPHY) { | ||||
| 		u32 val = rt_sysc_r32(SYSC_REG_CFG1); | ||||
|  | ||||
| 		val |= 3 << 14; | ||||
| 		rt_sysc_w32(val, SYSC_REG_CFG1); | ||||
| 		_mt7620_mii_write(gsw, 4, 30, 0xa000); | ||||
| 		_mt7620_mii_write(gsw, 4, 4, 0x05e1); | ||||
| 		_mt7620_mii_write(gsw, 4, 16, 0x1313); | ||||
| 		pr_info("gsw: setting port4 to ephy mode\n"); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static const struct of_device_id mediatek_gsw_match[] = { | ||||
| 	{ .compatible = "mediatek,mt7620-gsw" }, | ||||
| 	{}, | ||||
| }; | ||||
| MODULE_DEVICE_TABLE(of, mediatek_gsw_match); | ||||
|  | ||||
| int mtk_gsw_init(struct fe_priv *priv) | ||||
| { | ||||
| 	struct device_node *np = priv->switch_np; | ||||
| 	struct platform_device *pdev = of_find_device_by_node(np); | ||||
| 	struct mt7620_gsw *gsw; | ||||
|  | ||||
| 	if (!pdev) | ||||
| 		return -ENODEV; | ||||
|  | ||||
| 	if (!of_device_is_compatible(np, mediatek_gsw_match->compatible)) | ||||
| 		return -EINVAL; | ||||
|  | ||||
| 	gsw = platform_get_drvdata(pdev); | ||||
| 	priv->soc->swpriv = gsw; | ||||
|  | ||||
| 	mt7620_hw_init(gsw, np); | ||||
|  | ||||
| 	if (gsw->irq) { | ||||
| 		request_irq(gsw->irq, gsw_interrupt_mt7620, 0, | ||||
| 			    "gsw", priv); | ||||
| 		mtk_switch_w32(gsw, ~PORT_IRQ_ST_CHG, GSW_REG_IMR); | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int mt7620_gsw_probe(struct platform_device *pdev) | ||||
| { | ||||
| 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||||
| 	const char *port4 = NULL; | ||||
| 	struct mt7620_gsw *gsw; | ||||
| 	struct device_node *np = pdev->dev.of_node; | ||||
|  | ||||
| 	gsw = devm_kzalloc(&pdev->dev, sizeof(struct mt7620_gsw), GFP_KERNEL); | ||||
| 	if (!gsw) | ||||
| 		return -ENOMEM; | ||||
|  | ||||
| 	gsw->base = devm_ioremap_resource(&pdev->dev, res); | ||||
| 	if (!gsw->base) | ||||
| 		return -EADDRNOTAVAIL; | ||||
|  | ||||
| 	gsw->dev = &pdev->dev; | ||||
|  | ||||
| 	of_property_read_string(np, "mediatek,port4", &port4); | ||||
| 	if (port4 && !strcmp(port4, "ephy")) | ||||
| 		gsw->port4 = PORT4_EPHY; | ||||
| 	else if (port4 && !strcmp(port4, "gmac")) | ||||
| 		gsw->port4 = PORT4_EXT; | ||||
| 	else | ||||
| 		gsw->port4 = PORT4_EPHY; | ||||
|  | ||||
| 	gsw->irq = platform_get_irq(pdev, 0); | ||||
|  | ||||
| 	platform_set_drvdata(pdev, gsw); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int mt7620_gsw_remove(struct platform_device *pdev) | ||||
| { | ||||
| 	platform_set_drvdata(pdev, NULL); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static struct platform_driver gsw_driver = { | ||||
| 	.probe = mt7620_gsw_probe, | ||||
| 	.remove = mt7620_gsw_remove, | ||||
| 	.driver = { | ||||
| 		.name = "mt7620-gsw", | ||||
| 		.owner = THIS_MODULE, | ||||
| 		.of_match_table = mediatek_gsw_match, | ||||
| 	}, | ||||
| }; | ||||
|  | ||||
| module_platform_driver(gsw_driver); | ||||
|  | ||||
| MODULE_LICENSE("GPL"); | ||||
| MODULE_AUTHOR("John Crispin <blogic@openwrt.org>"); | ||||
| MODULE_DESCRIPTION("GBit switch driver for Mediatek MT7620 SoC"); | ||||
| MODULE_VERSION(MTK_FE_DRV_VERSION); | ||||
| @@ -0,0 +1,121 @@ | ||||
| /*   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; version 2 of the License | ||||
|  * | ||||
|  *   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. | ||||
|  * | ||||
|  *   Copyright (C) 2009-2015 John Crispin <blogic@openwrt.org> | ||||
|  *   Copyright (C) 2009-2015 Felix Fietkau <nbd@nbd.name> | ||||
|  *   Copyright (C) 2013-2015 Michael Lee <igvtee@gmail.com> | ||||
|  */ | ||||
|  | ||||
| #ifndef _RALINK_GSW_MT7620_H__ | ||||
| #define _RALINK_GSW_MT7620_H__ | ||||
|  | ||||
| #define GSW_REG_PHY_TIMEOUT	(5 * HZ) | ||||
|  | ||||
| #ifdef CONFIG_SOC_MT7621 | ||||
| #define MT7620A_GSW_REG_PIAC	0x0004 | ||||
| #else | ||||
| #define MT7620A_GSW_REG_PIAC	0x7004 | ||||
| #endif | ||||
|  | ||||
| #define GSW_NUM_VLANS		16 | ||||
| #define GSW_NUM_VIDS		4096 | ||||
| #define GSW_NUM_PORTS		7 | ||||
| #define GSW_PORT6		6 | ||||
|  | ||||
| #define GSW_MDIO_ACCESS		BIT(31) | ||||
| #define GSW_MDIO_READ		BIT(19) | ||||
| #define GSW_MDIO_WRITE		BIT(18) | ||||
| #define GSW_MDIO_START		BIT(16) | ||||
| #define GSW_MDIO_ADDR_SHIFT	20 | ||||
| #define GSW_MDIO_REG_SHIFT	25 | ||||
|  | ||||
| #define GSW_REG_MIB_CNT_EN	0x4000 | ||||
|  | ||||
| #define GSW_REG_PORT_PMCR(x)	(0x3000 + (x * 0x100)) | ||||
| #define GSW_REG_PORT_STATUS(x)	(0x3008 + (x * 0x100)) | ||||
| #define GSW_REG_SMACCR0		0x3fE4 | ||||
| #define GSW_REG_SMACCR1		0x3fE8 | ||||
| #define GSW_REG_CKGCR		0x3ff0 | ||||
|  | ||||
| #define GSW_REG_IMR		0x7008 | ||||
| #define GSW_REG_ISR		0x700c | ||||
| #define GSW_REG_GPC1		0x7014 | ||||
|  | ||||
| #define SYSC_REG_CHIP_REV_ID	0x0c | ||||
| #define SYSC_REG_CFG1		0x14 | ||||
| #define RST_CTRL_MCM		BIT(2) | ||||
| #define SYSC_PAD_RGMII2_MDIO	0x58 | ||||
| #define SYSC_GPIO_MODE		0x60 | ||||
|  | ||||
| #define PORT_IRQ_ST_CHG		0x7f | ||||
|  | ||||
| #ifdef CONFIG_SOC_MT7621 | ||||
| #define ESW_PHY_POLLING		0x0000 | ||||
| #else | ||||
| #define ESW_PHY_POLLING		0x7000 | ||||
| #endif | ||||
|  | ||||
| #define	PMCR_IPG		BIT(18) | ||||
| #define	PMCR_MAC_MODE		BIT(16) | ||||
| #define	PMCR_FORCE		BIT(15) | ||||
| #define	PMCR_TX_EN		BIT(14) | ||||
| #define	PMCR_RX_EN		BIT(13) | ||||
| #define	PMCR_BACKOFF		BIT(9) | ||||
| #define	PMCR_BACKPRES		BIT(8) | ||||
| #define	PMCR_RX_FC		BIT(5) | ||||
| #define	PMCR_TX_FC		BIT(4) | ||||
| #define	PMCR_SPEED(_x)		(_x << 2) | ||||
| #define	PMCR_DUPLEX		BIT(1) | ||||
| #define	PMCR_LINK		BIT(0) | ||||
|  | ||||
| #define PHY_AN_EN		BIT(31) | ||||
| #define PHY_PRE_EN		BIT(30) | ||||
| #define PMY_MDC_CONF(_x)	((_x & 0x3f) << 24) | ||||
|  | ||||
|  | ||||
| enum { | ||||
| 	/* Global attributes. */ | ||||
| 	GSW_ATTR_ENABLE_VLAN, | ||||
| 	/* Port attributes. */ | ||||
| 	GSW_ATTR_PORT_UNTAG, | ||||
| }; | ||||
|  | ||||
| enum { | ||||
| 	PORT4_EPHY = 0, | ||||
| 	PORT4_EXT, | ||||
| }; | ||||
|  | ||||
| struct mt7620_gsw { | ||||
| 	struct device		*dev; | ||||
| 	void __iomem		*base; | ||||
| 	int			irq; | ||||
| 	int			port4; | ||||
| 	unsigned long int	autopoll; | ||||
| }; | ||||
|  | ||||
| void mtk_switch_w32(struct mt7620_gsw *gsw, u32 val, unsigned reg); | ||||
| u32 mtk_switch_r32(struct mt7620_gsw *gsw, unsigned reg); | ||||
| int mtk_gsw_init(struct fe_priv *priv); | ||||
|  | ||||
| int mt7620_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val); | ||||
| int mt7620_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg); | ||||
| void mt7620_mdio_link_adjust(struct fe_priv *priv, int port); | ||||
| int mt7620_has_carrier(struct fe_priv *priv); | ||||
| void mt7620_print_link_state(struct fe_priv *priv, int port, int link, | ||||
| 			     int speed, int duplex); | ||||
|  | ||||
| void mt7530_mdio_w32(struct mt7620_gsw *gsw, u32 reg, u32 val); | ||||
| u32 mt7530_mdio_r32(struct mt7620_gsw *gsw, u32 reg); | ||||
|  | ||||
| u32 _mt7620_mii_write(struct mt7620_gsw *gsw, u32 phy_addr, | ||||
| 			     u32 phy_register, u32 write_data); | ||||
| u32 _mt7620_mii_read(struct mt7620_gsw *gsw, int phy_addr, int phy_reg); | ||||
| void mt7620_handle_carrier(struct fe_priv *priv); | ||||
|  | ||||
| #endif | ||||
| @@ -0,0 +1,285 @@ | ||||
| /*   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; version 2 of the License | ||||
|  * | ||||
|  *   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. | ||||
|  * | ||||
|  *   Copyright (C) 2009-2015 John Crispin <blogic@openwrt.org> | ||||
|  *   Copyright (C) 2009-2015 Felix Fietkau <nbd@nbd.name> | ||||
|  *   Copyright (C) 2013-2015 Michael Lee <igvtee@gmail.com> | ||||
|  */ | ||||
|  | ||||
| #include <linux/module.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/types.h> | ||||
| #include <linux/platform_device.h> | ||||
| #include <linux/of_device.h> | ||||
| #include <linux/of_irq.h> | ||||
|  | ||||
| #include <ralink_regs.h> | ||||
|  | ||||
| #include "mtk_eth_soc.h" | ||||
| #include "gsw_mt7620.h" | ||||
|  | ||||
| void mtk_switch_w32(struct mt7620_gsw *gsw, u32 val, unsigned reg) | ||||
| { | ||||
| 	iowrite32(val, gsw->base + reg); | ||||
| } | ||||
|  | ||||
| u32 mtk_switch_r32(struct mt7620_gsw *gsw, unsigned reg) | ||||
| { | ||||
| 	return ioread32(gsw->base + reg); | ||||
| } | ||||
|  | ||||
| static irqreturn_t gsw_interrupt_mt7621(int irq, void *_priv) | ||||
| { | ||||
| 	struct fe_priv *priv = (struct fe_priv *)_priv; | ||||
| 	struct mt7620_gsw *gsw = (struct mt7620_gsw *)priv->soc->swpriv; | ||||
| 	u32 reg, i; | ||||
|  | ||||
| 	reg = mt7530_mdio_r32(gsw, 0x700c); | ||||
|  | ||||
| 	for (i = 0; i < 5; i++) | ||||
| 		if (reg & BIT(i)) { | ||||
| 			unsigned int link; | ||||
|  | ||||
| 			link = mt7530_mdio_r32(gsw, | ||||
| 					       0x3008 + (i * 0x100)) & 0x1; | ||||
|  | ||||
| 			if (link != priv->link[i]) { | ||||
| 				priv->link[i] = link; | ||||
| 				if (link) | ||||
| 					netdev_info(priv->netdev, | ||||
| 						    "port %d link up\n", i); | ||||
| 				else | ||||
| 					netdev_info(priv->netdev, | ||||
| 						    "port %d link down\n", i); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 	mt7620_handle_carrier(priv); | ||||
| 	mt7530_mdio_w32(gsw, 0x700c, 0x1f); | ||||
|  | ||||
| 	return IRQ_HANDLED; | ||||
| } | ||||
|  | ||||
| static void mt7621_hw_init(struct mt7620_gsw *gsw, struct device_node *np) | ||||
| { | ||||
| 	u32 i; | ||||
| 	u32 val; | ||||
|  | ||||
| 	/* wardware reset the switch */ | ||||
| 	fe_reset(RST_CTRL_MCM); | ||||
| 	mdelay(10); | ||||
|  | ||||
| 	/* reduce RGMII2 PAD driving strength */ | ||||
| 	rt_sysc_m32(3 << 4, 0, SYSC_PAD_RGMII2_MDIO); | ||||
|  | ||||
| 	/* gpio mux - RGMII1=Normal mode */ | ||||
| 	rt_sysc_m32(BIT(14), 0, SYSC_GPIO_MODE); | ||||
|  | ||||
| 	/* set GMAC1 RGMII mode */ | ||||
| 	rt_sysc_m32(3 << 12, 0, SYSC_REG_CFG1); | ||||
|  | ||||
| 	/* enable MDIO to control MT7530 */ | ||||
| 	rt_sysc_m32(3 << 12, 0, SYSC_GPIO_MODE); | ||||
|  | ||||
| 	/* turn off all PHYs */ | ||||
| 	for (i = 0; i <= 4; i++) { | ||||
| 		val = _mt7620_mii_read(gsw, i, 0x0); | ||||
| 		val |= BIT(11); | ||||
| 		_mt7620_mii_write(gsw, i, 0x0, val); | ||||
| 	} | ||||
|  | ||||
| 	/* reset the switch */ | ||||
| 	mt7530_mdio_w32(gsw, 0x7000, 0x3); | ||||
| 	usleep_range(10, 20); | ||||
|  | ||||
| 	if ((rt_sysc_r32(SYSC_REG_CHIP_REV_ID) & 0xFFFF) == 0x0101) { | ||||
| 		/* (GE1, Force 1000M/FD, FC ON, MAX_RX_LENGTH 1536) */ | ||||
| 		mtk_switch_w32(gsw, 0x2105e30b, 0x100); | ||||
| 		mt7530_mdio_w32(gsw, 0x3600, 0x5e30b); | ||||
| 	} else { | ||||
| 		/* (GE1, Force 1000M/FD, FC ON, MAX_RX_LENGTH 1536) */ | ||||
| 		mtk_switch_w32(gsw, 0x2105e33b, 0x100); | ||||
| 		mt7530_mdio_w32(gsw, 0x3600, 0x5e33b); | ||||
| 	} | ||||
|  | ||||
| 	/* (GE2, Link down) */ | ||||
| 	mtk_switch_w32(gsw, 0x8000, 0x200); | ||||
|  | ||||
| 	/* Enable Port 6, P5 as GMAC5, P5 disable */ | ||||
| 	val = mt7530_mdio_r32(gsw, 0x7804); | ||||
| 	val &= ~BIT(8); | ||||
| 	val |= BIT(6) | BIT(13) | BIT(16); | ||||
| 	mt7530_mdio_w32(gsw, 0x7804, val); | ||||
|  | ||||
| 	val = rt_sysc_r32(0x10); | ||||
| 	val = (val >> 6) & 0x7; | ||||
| 	if (val >= 6) { | ||||
| 		/* 25Mhz Xtal - do nothing */ | ||||
| 	} else if (val >= 3) { | ||||
| 		/* 40Mhz */ | ||||
|  | ||||
| 		/* disable MT7530 core clock */ | ||||
| 		_mt7620_mii_write(gsw, 0, 13, 0x1f); | ||||
| 		_mt7620_mii_write(gsw, 0, 14, 0x410); | ||||
| 		_mt7620_mii_write(gsw, 0, 13, 0x401f); | ||||
| 		_mt7620_mii_write(gsw, 0, 14, 0x0); | ||||
|  | ||||
| 		/* disable MT7530 PLL */ | ||||
| 		_mt7620_mii_write(gsw, 0, 13, 0x1f); | ||||
| 		_mt7620_mii_write(gsw, 0, 14, 0x40d); | ||||
| 		_mt7620_mii_write(gsw, 0, 13, 0x401f); | ||||
| 		_mt7620_mii_write(gsw, 0, 14, 0x2020); | ||||
|  | ||||
| 		/* for MT7530 core clock = 500Mhz */ | ||||
| 		_mt7620_mii_write(gsw, 0, 13, 0x1f); | ||||
| 		_mt7620_mii_write(gsw, 0, 14, 0x40e); | ||||
| 		_mt7620_mii_write(gsw, 0, 13, 0x401f); | ||||
| 		_mt7620_mii_write(gsw, 0, 14, 0x119); | ||||
|  | ||||
| 		/* enable MT7530 PLL */ | ||||
| 		_mt7620_mii_write(gsw, 0, 13, 0x1f); | ||||
| 		_mt7620_mii_write(gsw, 0, 14, 0x40d); | ||||
| 		_mt7620_mii_write(gsw, 0, 13, 0x401f); | ||||
| 		_mt7620_mii_write(gsw, 0, 14, 0x2820); | ||||
|  | ||||
| 		usleep_range(20, 40); | ||||
|  | ||||
| 		/* enable MT7530 core clock */ | ||||
| 		_mt7620_mii_write(gsw, 0, 13, 0x1f); | ||||
| 		_mt7620_mii_write(gsw, 0, 14, 0x410); | ||||
| 		_mt7620_mii_write(gsw, 0, 13, 0x401f); | ||||
| 	} else { | ||||
| 		/* 20Mhz Xtal - TODO */ | ||||
| 	} | ||||
|  | ||||
| 	/* RGMII */ | ||||
| 	_mt7620_mii_write(gsw, 0, 14, 0x1); | ||||
|  | ||||
| 	/* set MT7530 central align */ | ||||
| 	val = mt7530_mdio_r32(gsw, 0x7830); | ||||
| 	val &= ~BIT(0); | ||||
| 	val |= BIT(1); | ||||
| 	mt7530_mdio_w32(gsw, 0x7830, val); | ||||
| 	val = mt7530_mdio_r32(gsw, 0x7a40); | ||||
| 	val &= ~BIT(30); | ||||
| 	mt7530_mdio_w32(gsw, 0x7a40, val); | ||||
| 	mt7530_mdio_w32(gsw, 0x7a78, 0x855); | ||||
|  | ||||
| 	/* delay setting for 10/1000M */ | ||||
| 	mt7530_mdio_w32(gsw, 0x7b00, 0x102); | ||||
| 	mt7530_mdio_w32(gsw, 0x7b04, 0x14); | ||||
|  | ||||
| 	/* lower Tx Driving*/ | ||||
| 	mt7530_mdio_w32(gsw, 0x7a54, 0x44); | ||||
| 	mt7530_mdio_w32(gsw, 0x7a5c, 0x44); | ||||
| 	mt7530_mdio_w32(gsw, 0x7a64, 0x44); | ||||
| 	mt7530_mdio_w32(gsw, 0x7a6c, 0x44); | ||||
| 	mt7530_mdio_w32(gsw, 0x7a74, 0x44); | ||||
| 	mt7530_mdio_w32(gsw, 0x7a7c, 0x44); | ||||
|  | ||||
| 	/* turn on all PHYs */ | ||||
| 	for (i = 0; i <= 4; i++) { | ||||
| 		val = _mt7620_mii_read(gsw, i, 0); | ||||
| 		val &= ~BIT(11); | ||||
| 		_mt7620_mii_write(gsw, i, 0, val); | ||||
| 	} | ||||
|  | ||||
| 	/* enable irq */ | ||||
| 	val = mt7530_mdio_r32(gsw, 0x7808); | ||||
| 	val |= 3 << 16; | ||||
| 	mt7530_mdio_w32(gsw, 0x7808, val); | ||||
| } | ||||
|  | ||||
| static const struct of_device_id mediatek_gsw_match[] = { | ||||
| 	{ .compatible = "mediatek,mt7621-gsw" }, | ||||
| 	{}, | ||||
| }; | ||||
| MODULE_DEVICE_TABLE(of, mediatek_gsw_match); | ||||
|  | ||||
| int mtk_gsw_init(struct fe_priv *priv) | ||||
| { | ||||
| 	struct device_node *np = priv->switch_np; | ||||
| 	struct platform_device *pdev = of_find_device_by_node(np); | ||||
| 	struct mt7620_gsw *gsw; | ||||
|  | ||||
| 	if (!pdev) | ||||
| 		return -ENODEV; | ||||
|  | ||||
| 	if (!of_device_is_compatible(np, mediatek_gsw_match->compatible)) | ||||
| 		return -EINVAL; | ||||
|  | ||||
| 	gsw = platform_get_drvdata(pdev); | ||||
| 	priv->soc->swpriv = gsw; | ||||
|  | ||||
| 	mt7621_hw_init(gsw, np); | ||||
|  | ||||
| 	if (gsw->irq) { | ||||
| 		request_irq(gsw->irq, gsw_interrupt_mt7621, 0, | ||||
| 			    "gsw", priv); | ||||
| 		mt7530_mdio_w32(gsw, 0x7008, 0x1f); | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int mt7621_gsw_probe(struct platform_device *pdev) | ||||
| { | ||||
| 	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||||
| 	const char *port4 = NULL; | ||||
| 	struct mt7620_gsw *gsw; | ||||
| 	struct device_node *np; | ||||
|  | ||||
| 	gsw = devm_kzalloc(&pdev->dev, sizeof(struct mt7620_gsw), GFP_KERNEL); | ||||
| 	if (!gsw) | ||||
| 		return -ENOMEM; | ||||
|  | ||||
| 	gsw->base = devm_ioremap_resource(&pdev->dev, res); | ||||
| 	if (!gsw->base) | ||||
| 		return -EADDRNOTAVAIL; | ||||
|  | ||||
| 	gsw->dev = &pdev->dev; | ||||
|  | ||||
| 	of_property_read_string(np, "mediatek,port4", &port4); | ||||
| 	if (port4 && !strcmp(port4, "ephy")) | ||||
| 		gsw->port4 = PORT4_EPHY; | ||||
| 	else if (port4 && !strcmp(port4, "gmac")) | ||||
| 		gsw->port4 = PORT4_EXT; | ||||
| 	else | ||||
| 		gsw->port4 = PORT4_EPHY; | ||||
|  | ||||
| 	gsw->irq = platform_get_irq(pdev, 0); | ||||
|  | ||||
| 	platform_set_drvdata(pdev, gsw); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int mt7621_gsw_remove(struct platform_device *pdev) | ||||
| { | ||||
| 	platform_set_drvdata(pdev, NULL); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static struct platform_driver gsw_driver = { | ||||
| 	.probe = mt7621_gsw_probe, | ||||
| 	.remove = mt7621_gsw_remove, | ||||
| 	.driver = { | ||||
| 		.name = "mt7621-gsw", | ||||
| 		.owner = THIS_MODULE, | ||||
| 		.of_match_table = mediatek_gsw_match, | ||||
| 	}, | ||||
| }; | ||||
|  | ||||
| module_platform_driver(gsw_driver); | ||||
|  | ||||
| MODULE_LICENSE("GPL"); | ||||
| MODULE_AUTHOR("John Crispin <blogic@openwrt.org>"); | ||||
| MODULE_DESCRIPTION("GBit switch driver for Mediatek MT7621 SoC"); | ||||
| MODULE_VERSION(MTK_FE_DRV_VERSION); | ||||
							
								
								
									
										259
									
								
								target/linux/ramips/files-4.9/drivers/net/ethernet/mtk/mdio.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										259
									
								
								target/linux/ramips/files-4.9/drivers/net/ethernet/mtk/mdio.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,259 @@ | ||||
| /*   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; version 2 of the License | ||||
|  * | ||||
|  *   Copyright (C) 2009-2015 John Crispin <blogic@openwrt.org> | ||||
|  *   Copyright (C) 2009-2015 Felix Fietkau <nbd@nbd.name> | ||||
|  *   Copyright (C) 2013-2015 Michael Lee <igvtee@gmail.com> | ||||
|  */ | ||||
|  | ||||
| #include <linux/module.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/phy.h> | ||||
| #include <linux/of_net.h> | ||||
| #include <linux/of_mdio.h> | ||||
|  | ||||
| #include "mtk_eth_soc.h" | ||||
| #include "mdio.h" | ||||
|  | ||||
| static int fe_mdio_reset(struct mii_bus *bus) | ||||
| { | ||||
| 	/* TODO */ | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static void fe_phy_link_adjust(struct net_device *dev) | ||||
| { | ||||
| 	struct fe_priv *priv = netdev_priv(dev); | ||||
| 	unsigned long flags; | ||||
| 	int i; | ||||
|  | ||||
| 	spin_lock_irqsave(&priv->phy->lock, flags); | ||||
| 	for (i = 0; i < 8; i++) { | ||||
| 		if (priv->phy->phy_node[i]) { | ||||
| 			struct phy_device *phydev = priv->phy->phy[i]; | ||||
| 			int status_change = 0; | ||||
|  | ||||
| 			if (phydev->link) | ||||
| 				if (priv->phy->duplex[i] != phydev->duplex || | ||||
| 				    priv->phy->speed[i] != phydev->speed) | ||||
| 					status_change = 1; | ||||
|  | ||||
| 			if (phydev->link != priv->link[i]) | ||||
| 				status_change = 1; | ||||
|  | ||||
| 			switch (phydev->speed) { | ||||
| 			case SPEED_1000: | ||||
| 			case SPEED_100: | ||||
| 			case SPEED_10: | ||||
| 				priv->link[i] = phydev->link; | ||||
| 				priv->phy->duplex[i] = phydev->duplex; | ||||
| 				priv->phy->speed[i] = phydev->speed; | ||||
|  | ||||
| 				if (status_change && | ||||
| 				    priv->soc->mdio_adjust_link) | ||||
| 					priv->soc->mdio_adjust_link(priv, i); | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int fe_connect_phy_node(struct fe_priv *priv, struct device_node *phy_node) | ||||
| { | ||||
| 	const __be32 *_port = NULL; | ||||
| 	struct phy_device *phydev; | ||||
| 	int phy_mode, port; | ||||
|  | ||||
| 	_port = of_get_property(phy_node, "reg", NULL); | ||||
|  | ||||
| 	if (!_port || (be32_to_cpu(*_port) >= 0x20)) { | ||||
| 		pr_err("%s: invalid port id\n", phy_node->name); | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
| 	port = be32_to_cpu(*_port); | ||||
| 	phy_mode = of_get_phy_mode(phy_node); | ||||
| 	if (phy_mode < 0) { | ||||
| 		dev_err(priv->device, "incorrect phy-mode %d\n", phy_mode); | ||||
| 		priv->phy->phy_node[port] = NULL; | ||||
| 		return -EINVAL; | ||||
| 	} | ||||
|  | ||||
| 	phydev = of_phy_connect(priv->netdev, phy_node, fe_phy_link_adjust, | ||||
| 				0, phy_mode); | ||||
| 	if (IS_ERR(phydev)) { | ||||
| 		dev_err(priv->device, "could not connect to PHY\n"); | ||||
| 		priv->phy->phy_node[port] = NULL; | ||||
| 		return PTR_ERR(phydev); | ||||
| 	} | ||||
|  | ||||
| 	phydev->supported &= PHY_GBIT_FEATURES; | ||||
| 	phydev->advertising = phydev->supported; | ||||
| 	phydev->no_auto_carrier_off = 1; | ||||
|  | ||||
| 	dev_info(priv->device, | ||||
| 		 "connected port %d to PHY at %s [uid=%08x, driver=%s]\n", | ||||
| 		 port, dev_name(&phydev->mdio.dev), phydev->phy_id, | ||||
| 		 phydev->drv->name); | ||||
|  | ||||
| 	priv->phy->phy[port] = phydev; | ||||
| 	priv->link[port] = 0; | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static void phy_init(struct fe_priv *priv, struct phy_device *phy) | ||||
| { | ||||
| 	phy_attach(priv->netdev, dev_name(&phy->mdio.dev), PHY_INTERFACE_MODE_MII); | ||||
|  | ||||
| 	phy->autoneg = AUTONEG_ENABLE; | ||||
| 	phy->speed = 0; | ||||
| 	phy->duplex = 0; | ||||
| 	phy->supported &= PHY_BASIC_FEATURES; | ||||
| 	phy->advertising = phy->supported | ADVERTISED_Autoneg; | ||||
|  | ||||
| 	phy_start_aneg(phy); | ||||
| } | ||||
|  | ||||
| static int fe_phy_connect(struct fe_priv *priv) | ||||
| { | ||||
| 	int i; | ||||
|  | ||||
| 	for (i = 0; i < 8; i++) { | ||||
| 		if (priv->phy->phy_node[i]) { | ||||
| 			if (!priv->phy_dev) { | ||||
| 				priv->phy_dev = priv->phy->phy[i]; | ||||
| 				priv->phy_flags = FE_PHY_FLAG_PORT; | ||||
| 			} | ||||
| 		} else if (priv->mii_bus && mdiobus_get_phy(priv->mii_bus, i)) { | ||||
| 			phy_init(priv, mdiobus_get_phy(priv->mii_bus, i)); | ||||
| 			if (!priv->phy_dev) { | ||||
| 				priv->phy_dev = mdiobus_get_phy(priv->mii_bus, i); | ||||
| 				priv->phy_flags = FE_PHY_FLAG_ATTACH; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static void fe_phy_disconnect(struct fe_priv *priv) | ||||
| { | ||||
| 	unsigned long flags; | ||||
| 	int i; | ||||
|  | ||||
| 	for (i = 0; i < 8; i++) | ||||
| 		if (priv->phy->phy_fixed[i]) { | ||||
| 			spin_lock_irqsave(&priv->phy->lock, flags); | ||||
| 			priv->link[i] = 0; | ||||
| 			if (priv->soc->mdio_adjust_link) | ||||
| 				priv->soc->mdio_adjust_link(priv, i); | ||||
| 			spin_unlock_irqrestore(&priv->phy->lock, flags); | ||||
| 		} else if (priv->phy->phy[i]) { | ||||
| 			phy_disconnect(priv->phy->phy[i]); | ||||
| 		} else if (priv->mii_bus && mdiobus_get_phy(priv->mii_bus, i)) { | ||||
| 			phy_detach(mdiobus_get_phy(priv->mii_bus, i)); | ||||
| 		} | ||||
| } | ||||
|  | ||||
| static void fe_phy_start(struct fe_priv *priv) | ||||
| { | ||||
| 	unsigned long flags; | ||||
| 	int i; | ||||
|  | ||||
| 	for (i = 0; i < 8; i++) { | ||||
| 		if (priv->phy->phy_fixed[i]) { | ||||
| 			spin_lock_irqsave(&priv->phy->lock, flags); | ||||
| 			priv->link[i] = 1; | ||||
| 			if (priv->soc->mdio_adjust_link) | ||||
| 				priv->soc->mdio_adjust_link(priv, i); | ||||
| 			spin_unlock_irqrestore(&priv->phy->lock, flags); | ||||
| 		} else if (priv->phy->phy[i]) { | ||||
| 			phy_start(priv->phy->phy[i]); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void fe_phy_stop(struct fe_priv *priv) | ||||
| { | ||||
| 	unsigned long flags; | ||||
| 	int i; | ||||
|  | ||||
| 	for (i = 0; i < 8; i++) | ||||
| 		if (priv->phy->phy_fixed[i]) { | ||||
| 			spin_lock_irqsave(&priv->phy->lock, flags); | ||||
| 			priv->link[i] = 0; | ||||
| 			if (priv->soc->mdio_adjust_link) | ||||
| 				priv->soc->mdio_adjust_link(priv, i); | ||||
| 			spin_unlock_irqrestore(&priv->phy->lock, flags); | ||||
| 		} else if (priv->phy->phy[i]) { | ||||
| 			phy_stop(priv->phy->phy[i]); | ||||
| 		} | ||||
| } | ||||
|  | ||||
| static struct fe_phy phy_ralink = { | ||||
| 	.connect = fe_phy_connect, | ||||
| 	.disconnect = fe_phy_disconnect, | ||||
| 	.start = fe_phy_start, | ||||
| 	.stop = fe_phy_stop, | ||||
| }; | ||||
|  | ||||
| int fe_mdio_init(struct fe_priv *priv) | ||||
| { | ||||
| 	struct device_node *mii_np; | ||||
| 	int err; | ||||
|  | ||||
| 	if (!priv->soc->mdio_read || !priv->soc->mdio_write) | ||||
| 		return 0; | ||||
|  | ||||
| 	spin_lock_init(&phy_ralink.lock); | ||||
| 	priv->phy = &phy_ralink; | ||||
|  | ||||
| 	mii_np = of_get_child_by_name(priv->device->of_node, "mdio-bus"); | ||||
| 	if (!mii_np) { | ||||
| 		dev_err(priv->device, "no %s child node found", "mdio-bus"); | ||||
| 		return -ENODEV; | ||||
| 	} | ||||
|  | ||||
| 	if (!of_device_is_available(mii_np)) { | ||||
| 		err = 0; | ||||
| 		goto err_put_node; | ||||
| 	} | ||||
|  | ||||
| 	priv->mii_bus = mdiobus_alloc(); | ||||
| 	if (!priv->mii_bus) { | ||||
| 		err = -ENOMEM; | ||||
| 		goto err_put_node; | ||||
| 	} | ||||
|  | ||||
| 	priv->mii_bus->name = "mdio"; | ||||
| 	priv->mii_bus->read = priv->soc->mdio_read; | ||||
| 	priv->mii_bus->write = priv->soc->mdio_write; | ||||
| 	priv->mii_bus->reset = fe_mdio_reset; | ||||
| 	priv->mii_bus->priv = priv; | ||||
| 	priv->mii_bus->parent = priv->device; | ||||
|  | ||||
| 	snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%s", mii_np->name); | ||||
| 	err = of_mdiobus_register(priv->mii_bus, mii_np); | ||||
| 	if (err) | ||||
| 		goto err_free_bus; | ||||
|  | ||||
| 	return 0; | ||||
|  | ||||
| err_free_bus: | ||||
| 	kfree(priv->mii_bus); | ||||
| err_put_node: | ||||
| 	of_node_put(mii_np); | ||||
| 	priv->mii_bus = NULL; | ||||
| 	return err; | ||||
| } | ||||
|  | ||||
| void fe_mdio_cleanup(struct fe_priv *priv) | ||||
| { | ||||
| 	if (!priv->mii_bus) | ||||
| 		return; | ||||
|  | ||||
| 	mdiobus_unregister(priv->mii_bus); | ||||
| 	of_node_put(priv->mii_bus->dev.of_node); | ||||
| 	kfree(priv->mii_bus); | ||||
| } | ||||
| @@ -0,0 +1,27 @@ | ||||
| /*   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; version 2 of the License | ||||
|  * | ||||
|  *   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. | ||||
|  * | ||||
|  *   Copyright (C) 2009-2015 John Crispin <blogic@openwrt.org> | ||||
|  *   Copyright (C) 2009-2015 Felix Fietkau <nbd@nbd.name> | ||||
|  *   Copyright (C) 2013-2015 Michael Lee <igvtee@gmail.com> | ||||
|  */ | ||||
|  | ||||
| #ifndef _RALINK_MDIO_H__ | ||||
| #define _RALINK_MDIO_H__ | ||||
|  | ||||
| #ifdef CONFIG_NET_MEDIATEK_MDIO | ||||
| int fe_mdio_init(struct fe_priv *priv); | ||||
| void fe_mdio_cleanup(struct fe_priv *priv); | ||||
| int fe_connect_phy_node(struct fe_priv *priv, | ||||
| 			struct device_node *phy_node); | ||||
| #else | ||||
| static inline int fe_mdio_init(struct fe_priv *priv) { return 0; } | ||||
| static inline void fe_mdio_cleanup(struct fe_priv *priv) {} | ||||
| #endif | ||||
| #endif | ||||
| @@ -0,0 +1,168 @@ | ||||
| /*   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; version 2 of the License | ||||
|  * | ||||
|  *   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. | ||||
|  * | ||||
|  *   Copyright (C) 2009-2015 John Crispin <blogic@openwrt.org> | ||||
|  *   Copyright (C) 2009-2015 Felix Fietkau <nbd@nbd.name> | ||||
|  *   Copyright (C) 2013-2015 Michael Lee <igvtee@gmail.com> | ||||
|  */ | ||||
|  | ||||
| #include <linux/module.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/types.h> | ||||
|  | ||||
| #include "mtk_eth_soc.h" | ||||
| #include "gsw_mt7620.h" | ||||
| #include "mdio.h" | ||||
|  | ||||
| static int mt7620_mii_busy_wait(struct mt7620_gsw *gsw) | ||||
| { | ||||
| 	unsigned long t_start = jiffies; | ||||
|  | ||||
| 	while (1) { | ||||
| 		if (!(mtk_switch_r32(gsw, MT7620A_GSW_REG_PIAC) & GSW_MDIO_ACCESS)) | ||||
| 			return 0; | ||||
| 		if (time_after(jiffies, t_start + GSW_REG_PHY_TIMEOUT)) | ||||
| 			break; | ||||
| 	} | ||||
|  | ||||
| 	dev_err(gsw->dev, "mdio: MDIO timeout\n"); | ||||
| 	return -1; | ||||
| } | ||||
|  | ||||
| u32 _mt7620_mii_write(struct mt7620_gsw *gsw, u32 phy_addr, | ||||
| 			     u32 phy_register, u32 write_data) | ||||
| { | ||||
| 	if (mt7620_mii_busy_wait(gsw)) | ||||
| 		return -1; | ||||
|  | ||||
| 	write_data &= 0xffff; | ||||
|  | ||||
| 	mtk_switch_w32(gsw, GSW_MDIO_ACCESS | GSW_MDIO_START | GSW_MDIO_WRITE | | ||||
| 		(phy_register << GSW_MDIO_REG_SHIFT) | | ||||
| 		(phy_addr << GSW_MDIO_ADDR_SHIFT) | write_data, | ||||
| 		MT7620A_GSW_REG_PIAC); | ||||
|  | ||||
| 	if (mt7620_mii_busy_wait(gsw)) | ||||
| 		return -1; | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| u32 _mt7620_mii_read(struct mt7620_gsw *gsw, int phy_addr, int phy_reg) | ||||
| { | ||||
| 	u32 d; | ||||
|  | ||||
| 	if (mt7620_mii_busy_wait(gsw)) | ||||
| 		return 0xffff; | ||||
|  | ||||
| 	mtk_switch_w32(gsw, GSW_MDIO_ACCESS | GSW_MDIO_START | GSW_MDIO_READ | | ||||
| 		(phy_reg << GSW_MDIO_REG_SHIFT) | | ||||
| 		(phy_addr << GSW_MDIO_ADDR_SHIFT), | ||||
| 		MT7620A_GSW_REG_PIAC); | ||||
|  | ||||
| 	if (mt7620_mii_busy_wait(gsw)) | ||||
| 		return 0xffff; | ||||
|  | ||||
| 	d = mtk_switch_r32(gsw, MT7620A_GSW_REG_PIAC) & 0xffff; | ||||
|  | ||||
| 	return d; | ||||
| } | ||||
|  | ||||
| int mt7620_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val) | ||||
| { | ||||
| 	struct fe_priv *priv = bus->priv; | ||||
| 	struct mt7620_gsw *gsw = (struct mt7620_gsw *)priv->soc->swpriv; | ||||
|  | ||||
| 	return _mt7620_mii_write(gsw, phy_addr, phy_reg, val); | ||||
| } | ||||
|  | ||||
| int mt7620_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg) | ||||
| { | ||||
| 	struct fe_priv *priv = bus->priv; | ||||
| 	struct mt7620_gsw *gsw = (struct mt7620_gsw *)priv->soc->swpriv; | ||||
|  | ||||
| 	return _mt7620_mii_read(gsw, phy_addr, phy_reg); | ||||
| } | ||||
|  | ||||
| void mt7530_mdio_w32(struct mt7620_gsw *gsw, u32 reg, u32 val) | ||||
| { | ||||
| 	_mt7620_mii_write(gsw, 0x1f, 0x1f, (reg >> 6) & 0x3ff); | ||||
| 	_mt7620_mii_write(gsw, 0x1f, (reg >> 2) & 0xf,  val & 0xffff); | ||||
| 	_mt7620_mii_write(gsw, 0x1f, 0x10, val >> 16); | ||||
| } | ||||
|  | ||||
| u32 mt7530_mdio_r32(struct mt7620_gsw *gsw, u32 reg) | ||||
| { | ||||
| 	u16 high, low; | ||||
|  | ||||
| 	_mt7620_mii_write(gsw, 0x1f, 0x1f, (reg >> 6) & 0x3ff); | ||||
| 	low = _mt7620_mii_read(gsw, 0x1f, (reg >> 2) & 0xf); | ||||
| 	high = _mt7620_mii_read(gsw, 0x1f, 0x10); | ||||
|  | ||||
| 	return (high << 16) | (low & 0xffff); | ||||
| } | ||||
|  | ||||
| static unsigned char *fe_speed_str(int speed) | ||||
| { | ||||
| 	switch (speed) { | ||||
| 	case 2: | ||||
| 	case SPEED_1000: | ||||
| 		return "1000"; | ||||
| 	case 1: | ||||
| 	case SPEED_100: | ||||
| 		return "100"; | ||||
| 	case 0: | ||||
| 	case SPEED_10: | ||||
| 		return "10"; | ||||
| 	} | ||||
|  | ||||
| 	return "? "; | ||||
| } | ||||
|  | ||||
| int mt7620_has_carrier(struct fe_priv *priv) | ||||
| { | ||||
| 	struct mt7620_gsw *gsw = (struct mt7620_gsw *)priv->soc->swpriv; | ||||
| 	int i; | ||||
|  | ||||
| 	for (i = 0; i < GSW_PORT6; i++) | ||||
| 		if (mtk_switch_r32(gsw, GSW_REG_PORT_STATUS(i)) & 0x1) | ||||
| 			return 1; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
|  | ||||
| void mt7620_handle_carrier(struct fe_priv *priv) | ||||
| { | ||||
| 	if (!priv->phy) | ||||
| 		return; | ||||
|  | ||||
| 	if (mt7620_has_carrier(priv)) | ||||
| 		netif_carrier_on(priv->netdev); | ||||
| 	else | ||||
| 		netif_carrier_off(priv->netdev); | ||||
| } | ||||
|  | ||||
| void mt7620_print_link_state(struct fe_priv *priv, int port, int link, | ||||
| 			     int speed, int duplex) | ||||
| { | ||||
| 	if (link) | ||||
| 		netdev_info(priv->netdev, "port %d link up (%sMbps/%s duplex)\n", | ||||
| 			    port, fe_speed_str(speed), | ||||
| 			    (duplex) ? "Full" : "Half"); | ||||
| 	else | ||||
| 		netdev_info(priv->netdev, "port %d link down\n", port); | ||||
| } | ||||
|  | ||||
| void mt7620_mdio_link_adjust(struct fe_priv *priv, int port) | ||||
| { | ||||
| 	mt7620_print_link_state(priv, port, priv->link[port], | ||||
| 				priv->phy->speed[port], | ||||
| 				(priv->phy->duplex[port] == DUPLEX_FULL)); | ||||
| 	mt7620_handle_carrier(priv); | ||||
| } | ||||
| @@ -0,0 +1,222 @@ | ||||
| /*   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; version 2 of the License | ||||
|  * | ||||
|  *   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. | ||||
|  * | ||||
|  *   Copyright (C) 2009-2015 John Crispin <blogic@openwrt.org> | ||||
|  *   Copyright (C) 2009-2015 Felix Fietkau <nbd@nbd.name> | ||||
|  *   Copyright (C) 2013-2015 Michael Lee <igvtee@gmail.com> | ||||
|  */ | ||||
|  | ||||
| #include <linux/module.h> | ||||
| #include <linux/kernel.h> | ||||
| #include <linux/types.h> | ||||
| #include <linux/of_net.h> | ||||
| #include <linux/of_mdio.h> | ||||
|  | ||||
| #include "mtk_eth_soc.h" | ||||
| #include "mdio_rt2880.h" | ||||
| #include "mdio.h" | ||||
|  | ||||
| #define FE_MDIO_RETRY	1000 | ||||
|  | ||||
| static unsigned char *rt2880_speed_str(struct fe_priv *priv) | ||||
| { | ||||
| 	switch (priv->phy->speed[0]) { | ||||
| 	case SPEED_1000: | ||||
| 		return "1000"; | ||||
| 	case SPEED_100: | ||||
| 		return "100"; | ||||
| 	case SPEED_10: | ||||
| 		return "10"; | ||||
| 	} | ||||
|  | ||||
| 	return "?"; | ||||
| } | ||||
|  | ||||
| void rt2880_mdio_link_adjust(struct fe_priv *priv, int port) | ||||
| { | ||||
| 	u32 mdio_cfg; | ||||
|  | ||||
| 	if (!priv->link[0]) { | ||||
| 		netif_carrier_off(priv->netdev); | ||||
| 		netdev_info(priv->netdev, "link down\n"); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	mdio_cfg = FE_MDIO_CFG_TX_CLK_SKEW_200 | | ||||
| 		   FE_MDIO_CFG_RX_CLK_SKEW_200 | | ||||
| 		   FE_MDIO_CFG_GP1_FRC_EN; | ||||
|  | ||||
| 	if (priv->phy->duplex[0] == DUPLEX_FULL) | ||||
| 		mdio_cfg |= FE_MDIO_CFG_GP1_DUPLEX; | ||||
|  | ||||
| 	if (priv->phy->tx_fc[0]) | ||||
| 		mdio_cfg |= FE_MDIO_CFG_GP1_FC_TX; | ||||
|  | ||||
| 	if (priv->phy->rx_fc[0]) | ||||
| 		mdio_cfg |= FE_MDIO_CFG_GP1_FC_RX; | ||||
|  | ||||
| 	switch (priv->phy->speed[0]) { | ||||
| 	case SPEED_10: | ||||
| 		mdio_cfg |= FE_MDIO_CFG_GP1_SPEED_10; | ||||
| 		break; | ||||
| 	case SPEED_100: | ||||
| 		mdio_cfg |= FE_MDIO_CFG_GP1_SPEED_100; | ||||
| 		break; | ||||
| 	case SPEED_1000: | ||||
| 		mdio_cfg |= FE_MDIO_CFG_GP1_SPEED_1000; | ||||
| 		break; | ||||
| 	default: | ||||
| 		BUG(); | ||||
| 	} | ||||
|  | ||||
| 	fe_w32(mdio_cfg, FE_MDIO_CFG); | ||||
|  | ||||
| 	netif_carrier_on(priv->netdev); | ||||
| 	netdev_info(priv->netdev, "link up (%sMbps/%s duplex)\n", | ||||
| 		    rt2880_speed_str(priv), | ||||
| 		    (priv->phy->duplex[0] == DUPLEX_FULL) ? "Full" : "Half"); | ||||
| } | ||||
|  | ||||
| static int rt2880_mdio_wait_ready(struct fe_priv *priv) | ||||
| { | ||||
| 	int retries; | ||||
|  | ||||
| 	retries = FE_MDIO_RETRY; | ||||
| 	while (1) { | ||||
| 		u32 t; | ||||
|  | ||||
| 		t = fe_r32(FE_MDIO_ACCESS); | ||||
| 		if ((t & BIT(31)) == 0) | ||||
| 			return 0; | ||||
|  | ||||
| 		if (retries-- == 0) | ||||
| 			break; | ||||
|  | ||||
| 		udelay(1); | ||||
| 	} | ||||
|  | ||||
| 	dev_err(priv->device, "MDIO operation timed out\n"); | ||||
| 	return -ETIMEDOUT; | ||||
| } | ||||
|  | ||||
| int rt2880_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg) | ||||
| { | ||||
| 	struct fe_priv *priv = bus->priv; | ||||
| 	int err; | ||||
| 	u32 t; | ||||
|  | ||||
| 	err = rt2880_mdio_wait_ready(priv); | ||||
| 	if (err) | ||||
| 		return 0xffff; | ||||
|  | ||||
| 	t = (phy_addr << 24) | (phy_reg << 16); | ||||
| 	fe_w32(t, FE_MDIO_ACCESS); | ||||
| 	t |= BIT(31); | ||||
| 	fe_w32(t, FE_MDIO_ACCESS); | ||||
|  | ||||
| 	err = rt2880_mdio_wait_ready(priv); | ||||
| 	if (err) | ||||
| 		return 0xffff; | ||||
|  | ||||
| 	pr_debug("%s: addr=%04x, reg=%04x, value=%04x\n", __func__, | ||||
| 		 phy_addr, phy_reg, fe_r32(FE_MDIO_ACCESS) & 0xffff); | ||||
|  | ||||
| 	return fe_r32(FE_MDIO_ACCESS) & 0xffff; | ||||
| } | ||||
|  | ||||
| int rt2880_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val) | ||||
| { | ||||
| 	struct fe_priv *priv = bus->priv; | ||||
| 	int err; | ||||
| 	u32 t; | ||||
|  | ||||
| 	pr_debug("%s: addr=%04x, reg=%04x, value=%04x\n", __func__, | ||||
| 		 phy_addr, phy_reg, fe_r32(FE_MDIO_ACCESS) & 0xffff); | ||||
|  | ||||
| 	err = rt2880_mdio_wait_ready(priv); | ||||
| 	if (err) | ||||
| 		return err; | ||||
|  | ||||
| 	t = (1 << 30) | (phy_addr << 24) | (phy_reg << 16) | val; | ||||
| 	fe_w32(t, FE_MDIO_ACCESS); | ||||
| 	t |= BIT(31); | ||||
| 	fe_w32(t, FE_MDIO_ACCESS); | ||||
|  | ||||
| 	return rt2880_mdio_wait_ready(priv); | ||||
| } | ||||
|  | ||||
| void rt2880_port_init(struct fe_priv *priv, struct device_node *np) | ||||
| { | ||||
| 	const __be32 *id = of_get_property(np, "reg", NULL); | ||||
| 	const __be32 *link; | ||||
| 	int size; | ||||
| 	int phy_mode; | ||||
|  | ||||
| 	if (!id || (be32_to_cpu(*id) != 0)) { | ||||
| 		pr_err("%s: invalid port id\n", np->name); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	priv->phy->phy_fixed[0] = of_get_property(np, | ||||
| 						  "mediatek,fixed-link", &size); | ||||
| 	if (priv->phy->phy_fixed[0] && | ||||
| 	    (size != (4 * sizeof(*priv->phy->phy_fixed[0])))) { | ||||
| 		pr_err("%s: invalid fixed link property\n", np->name); | ||||
| 		priv->phy->phy_fixed[0] = NULL; | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	phy_mode = of_get_phy_mode(np); | ||||
| 	switch (phy_mode) { | ||||
| 	case PHY_INTERFACE_MODE_RGMII: | ||||
| 		break; | ||||
| 	case PHY_INTERFACE_MODE_MII: | ||||
| 		break; | ||||
| 	case PHY_INTERFACE_MODE_RMII: | ||||
| 		break; | ||||
| 	default: | ||||
| 		if (!priv->phy->phy_fixed[0]) | ||||
| 			dev_err(priv->device, "port %d - invalid phy mode\n", | ||||
| 				priv->phy->speed[0]); | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
| 	priv->phy->phy_node[0] = of_parse_phandle(np, "phy-handle", 0); | ||||
| 	if (!priv->phy->phy_node[0] && !priv->phy->phy_fixed[0]) | ||||
| 		return; | ||||
|  | ||||
| 	if (priv->phy->phy_fixed[0]) { | ||||
| 		link = priv->phy->phy_fixed[0]; | ||||
| 		priv->phy->speed[0] = be32_to_cpup(link++); | ||||
| 		priv->phy->duplex[0] = be32_to_cpup(link++); | ||||
| 		priv->phy->tx_fc[0] = be32_to_cpup(link++); | ||||
| 		priv->phy->rx_fc[0] = be32_to_cpup(link++); | ||||
|  | ||||
| 		priv->link[0] = 1; | ||||
| 		switch (priv->phy->speed[0]) { | ||||
| 		case SPEED_10: | ||||
| 			break; | ||||
| 		case SPEED_100: | ||||
| 			break; | ||||
| 		case SPEED_1000: | ||||
| 			break; | ||||
| 		default: | ||||
| 			dev_err(priv->device, "invalid link speed: %d\n", | ||||
| 				priv->phy->speed[0]); | ||||
| 			priv->phy->phy_fixed[0] = 0; | ||||
| 			return; | ||||
| 		} | ||||
| 		dev_info(priv->device, "using fixed link parameters\n"); | ||||
| 		rt2880_mdio_link_adjust(priv, 0); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	if (priv->phy->phy_node[0] && mdiobus_get_phy(priv->mii_bus, 0)) | ||||
| 		fe_connect_phy_node(priv, priv->phy->phy_node[0]); | ||||
| } | ||||
| @@ -0,0 +1,23 @@ | ||||
| /*   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; version 2 of the License | ||||
|  * | ||||
|  *   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. | ||||
|  * | ||||
|  *   Copyright (C) 2009-2015 John Crispin <blogic@openwrt.org> | ||||
|  *   Copyright (C) 2009-2015 Felix Fietkau <nbd@nbd.name> | ||||
|  *   Copyright (C) 2013-2015 Michael Lee <igvtee@gmail.com> | ||||
|  */ | ||||
|  | ||||
| #ifndef _RALINK_MDIO_RT2880_H__ | ||||
| #define _RALINK_MDIO_RT2880_H__ | ||||
|  | ||||
| void rt2880_mdio_link_adjust(struct fe_priv *priv, int port); | ||||
| int rt2880_mdio_read(struct mii_bus *bus, int phy_addr, int phy_reg); | ||||
| int rt2880_mdio_write(struct mii_bus *bus, int phy_addr, int phy_reg, u16 val); | ||||
| void rt2880_port_init(struct fe_priv *priv, struct device_node *np); | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										895
									
								
								target/linux/ramips/files-4.9/drivers/net/ethernet/mtk/mt7530.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										895
									
								
								target/linux/ramips/files-4.9/drivers/net/ethernet/mtk/mt7530.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,895 @@ | ||||
| /* | ||||
|  * 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 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. | ||||
|  * | ||||
|  * Copyright (C) 2013 John Crispin <blogic@openwrt.org> | ||||
|  * Copyright (C) 2016 Vitaly Chekryzhev <13hakta@gmail.com> | ||||
|  */ | ||||
|  | ||||
| #include <linux/if.h> | ||||
| #include <linux/module.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/list.h> | ||||
| #include <linux/if_ether.h> | ||||
| #include <linux/skbuff.h> | ||||
| #include <linux/netdevice.h> | ||||
| #include <linux/netlink.h> | ||||
| #include <linux/bitops.h> | ||||
| #include <net/genetlink.h> | ||||
| #include <linux/switch.h> | ||||
| #include <linux/delay.h> | ||||
| #include <linux/phy.h> | ||||
| #include <linux/netdevice.h> | ||||
| #include <linux/etherdevice.h> | ||||
| #include <linux/lockdep.h> | ||||
| #include <linux/workqueue.h> | ||||
| #include <linux/of_device.h> | ||||
|  | ||||
| #include "mt7530.h" | ||||
|  | ||||
| #define MT7530_CPU_PORT		6 | ||||
| #define MT7530_NUM_PORTS	8 | ||||
| #ifdef CONFIG_SOC_MT7621 | ||||
| #define MT7530_NUM_VLANS	4095 | ||||
| #else | ||||
| #define MT7530_NUM_VLANS	16 | ||||
| #endif | ||||
| #define MT7530_MAX_VID		4095 | ||||
| #define MT7530_MIN_VID		0 | ||||
|  | ||||
| /* registers */ | ||||
| #define REG_ESW_VLAN_VTCR		0x90 | ||||
| #define REG_ESW_VLAN_VAWD1		0x94 | ||||
| #define REG_ESW_VLAN_VAWD2		0x98 | ||||
| #define REG_ESW_VLAN_VTIM(x)	(0x100 + 4 * ((x) / 2)) | ||||
|  | ||||
| #define REG_ESW_VLAN_VAWD1_IVL_MAC	BIT(30) | ||||
| #define REG_ESW_VLAN_VAWD1_VTAG_EN	BIT(28) | ||||
| #define REG_ESW_VLAN_VAWD1_VALID	BIT(0) | ||||
|  | ||||
| /* vlan egress mode */ | ||||
| enum { | ||||
| 	ETAG_CTRL_UNTAG	= 0, | ||||
| 	ETAG_CTRL_TAG	= 2, | ||||
| 	ETAG_CTRL_SWAP	= 1, | ||||
| 	ETAG_CTRL_STACK	= 3, | ||||
| }; | ||||
|  | ||||
| #define REG_ESW_PORT_PCR(x)	(0x2004 | ((x) << 8)) | ||||
| #define REG_ESW_PORT_PVC(x)	(0x2010 | ((x) << 8)) | ||||
| #define REG_ESW_PORT_PPBV1(x)	(0x2014 | ((x) << 8)) | ||||
|  | ||||
| #define REG_HWTRAP		0x7804 | ||||
|  | ||||
| #define MIB_DESC(_s , _o, _n)   \ | ||||
| 	{                       \ | ||||
| 		.size = (_s),   \ | ||||
| 		.offset = (_o), \ | ||||
| 		.name = (_n),   \ | ||||
| 	} | ||||
|  | ||||
| struct mt7xxx_mib_desc { | ||||
| 	unsigned int size; | ||||
| 	unsigned int offset; | ||||
| 	const char *name; | ||||
| }; | ||||
|  | ||||
| static const struct mt7xxx_mib_desc mt7620_mibs[] = { | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_PPE_AC_BCNT0, "PPE_AC_BCNT0"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_PPE_AC_PCNT0, "PPE_AC_PCNT0"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_PPE_AC_BCNT63, "PPE_AC_BCNT63"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_PPE_AC_PCNT63, "PPE_AC_PCNT63"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_PPE_MTR_CNT0, "PPE_MTR_CNT0"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_PPE_MTR_CNT63, "PPE_MTR_CNT63"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_GDM1_TX_GBCNT, "GDM1_TX_GBCNT"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_GDM1_TX_GPCNT, "GDM1_TX_GPCNT"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_GDM1_TX_SKIPCNT, "GDM1_TX_SKIPCNT"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_GDM1_TX_COLCNT, "GDM1_TX_COLCNT"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_GDM1_RX_GBCNT1, "GDM1_RX_GBCNT1"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_GDM1_RX_GPCNT1, "GDM1_RX_GPCNT1"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_GDM1_RX_OERCNT, "GDM1_RX_OERCNT"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_GDM1_RX_FERCNT, "GDM1_RX_FERCNT"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_GDM1_RX_SERCNT, "GDM1_RX_SERCNT"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_GDM1_RX_LERCNT, "GDM1_RX_LERCNT"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_GDM1_RX_CERCNT, "GDM1_RX_CERCNT"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_GDM1_RX_FCCNT, "GDM1_RX_FCCNT"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_GDM2_TX_GBCNT, "GDM2_TX_GBCNT"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_GDM2_TX_GPCNT, "GDM2_TX_GPCNT"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_GDM2_TX_SKIPCNT, "GDM2_TX_SKIPCNT"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_GDM2_TX_COLCNT, "GDM2_TX_COLCNT"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_GDM2_RX_GBCNT, "GDM2_RX_GBCNT"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_GDM2_RX_GPCNT, "GDM2_RX_GPCNT"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_GDM2_RX_OERCNT, "GDM2_RX_OERCNT"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_GDM2_RX_FERCNT, "GDM2_RX_FERCNT"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_GDM2_RX_SERCNT, "GDM2_RX_SERCNT"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_GDM2_RX_LERCNT, "GDM2_RX_LERCNT"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_GDM2_RX_CERCNT, "GDM2_RX_CERCNT"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_GDM2_RX_FCCNT, "GDM2_RX_FCCNT") | ||||
| }; | ||||
|  | ||||
| static const struct mt7xxx_mib_desc mt7620_port_mibs[] = { | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_PORT_TGPCN,  "TxGPC"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_PORT_TBOCN,  "TxBOC"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_PORT_TGOCN,  "TxGOC"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_PORT_TEPCN,  "TxEPC"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_PORT_RGPCN,  "RxGPC"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_PORT_RBOCN,  "RxBOC"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_PORT_RGOCN,  "RxGOC"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_PORT_REPC1N, "RxEPC1"), | ||||
| 	MIB_DESC(1, MT7620_MIB_STATS_PORT_REPC2N, "RxEPC2") | ||||
| }; | ||||
|  | ||||
| static const struct mt7xxx_mib_desc mt7621_mibs[] = { | ||||
| 	MIB_DESC(1, MT7621_STATS_TDPC, "TxDrop"), | ||||
| 	MIB_DESC(1, MT7621_STATS_TCRC, "TxCRC"), | ||||
| 	MIB_DESC(1, MT7621_STATS_TUPC, "TxUni"), | ||||
| 	MIB_DESC(1, MT7621_STATS_TMPC, "TxMulti"), | ||||
| 	MIB_DESC(1, MT7621_STATS_TBPC, "TxBroad"), | ||||
| 	MIB_DESC(1, MT7621_STATS_TCEC, "TxCollision"), | ||||
| 	MIB_DESC(1, MT7621_STATS_TSCEC, "TxSingleCol"), | ||||
| 	MIB_DESC(1, MT7621_STATS_TMCEC, "TxMultiCol"), | ||||
| 	MIB_DESC(1, MT7621_STATS_TDEC, "TxDefer"), | ||||
| 	MIB_DESC(1, MT7621_STATS_TLCEC, "TxLateCol"), | ||||
| 	MIB_DESC(1, MT7621_STATS_TXCEC, "TxExcCol"), | ||||
| 	MIB_DESC(1, MT7621_STATS_TPPC, "TxPause"), | ||||
| 	MIB_DESC(1, MT7621_STATS_TL64PC, "Tx64Byte"), | ||||
| 	MIB_DESC(1, MT7621_STATS_TL65PC, "Tx65Byte"), | ||||
| 	MIB_DESC(1, MT7621_STATS_TL128PC, "Tx128Byte"), | ||||
| 	MIB_DESC(1, MT7621_STATS_TL256PC, "Tx256Byte"), | ||||
| 	MIB_DESC(1, MT7621_STATS_TL512PC, "Tx512Byte"), | ||||
| 	MIB_DESC(1, MT7621_STATS_TL1024PC, "Tx1024Byte"), | ||||
| 	MIB_DESC(2, MT7621_STATS_TOC, "TxByte"), | ||||
| 	MIB_DESC(1, MT7621_STATS_RDPC, "RxDrop"), | ||||
| 	MIB_DESC(1, MT7621_STATS_RFPC, "RxFiltered"), | ||||
| 	MIB_DESC(1, MT7621_STATS_RUPC, "RxUni"), | ||||
| 	MIB_DESC(1, MT7621_STATS_RMPC, "RxMulti"), | ||||
| 	MIB_DESC(1, MT7621_STATS_RBPC, "RxBroad"), | ||||
| 	MIB_DESC(1, MT7621_STATS_RAEPC, "RxAlignErr"), | ||||
| 	MIB_DESC(1, MT7621_STATS_RCEPC, "RxCRC"), | ||||
| 	MIB_DESC(1, MT7621_STATS_RUSPC, "RxUnderSize"), | ||||
| 	MIB_DESC(1, MT7621_STATS_RFEPC, "RxFragment"), | ||||
| 	MIB_DESC(1, MT7621_STATS_ROSPC, "RxOverSize"), | ||||
| 	MIB_DESC(1, MT7621_STATS_RJEPC, "RxJabber"), | ||||
| 	MIB_DESC(1, MT7621_STATS_RPPC, "RxPause"), | ||||
| 	MIB_DESC(1, MT7621_STATS_RL64PC, "Rx64Byte"), | ||||
| 	MIB_DESC(1, MT7621_STATS_RL65PC, "Rx65Byte"), | ||||
| 	MIB_DESC(1, MT7621_STATS_RL128PC, "Rx128Byte"), | ||||
| 	MIB_DESC(1, MT7621_STATS_RL256PC, "Rx256Byte"), | ||||
| 	MIB_DESC(1, MT7621_STATS_RL512PC, "Rx512Byte"), | ||||
| 	MIB_DESC(1, MT7621_STATS_RL1024PC, "Rx1024Byte"), | ||||
| 	MIB_DESC(2, MT7621_STATS_ROC, "RxByte"), | ||||
| 	MIB_DESC(1, MT7621_STATS_RDPC_CTRL, "RxCtrlDrop"), | ||||
| 	MIB_DESC(1, MT7621_STATS_RDPC_ING, "RxIngDrop"), | ||||
| 	MIB_DESC(1, MT7621_STATS_RDPC_ARL, "RxARLDrop") | ||||
| }; | ||||
|  | ||||
| enum { | ||||
| 	/* Global attributes. */ | ||||
| 	MT7530_ATTR_ENABLE_VLAN, | ||||
| }; | ||||
|  | ||||
| struct mt7530_port_entry { | ||||
| 	u16	pvid; | ||||
| }; | ||||
|  | ||||
| struct mt7530_vlan_entry { | ||||
| 	u16	vid; | ||||
| 	u8	member; | ||||
| 	u8	etags; | ||||
| }; | ||||
|  | ||||
| struct mt7530_priv { | ||||
| 	void __iomem		*base; | ||||
| 	struct mii_bus		*bus; | ||||
| 	struct switch_dev	swdev; | ||||
|  | ||||
| 	bool			global_vlan_enable; | ||||
| 	struct mt7530_vlan_entry	vlan_entries[MT7530_NUM_VLANS]; | ||||
| 	struct mt7530_port_entry	port_entries[MT7530_NUM_PORTS]; | ||||
| }; | ||||
|  | ||||
| struct mt7530_mapping { | ||||
| 	char	*name; | ||||
| 	u16	pvids[MT7530_NUM_PORTS]; | ||||
| 	u8	members[MT7530_NUM_VLANS]; | ||||
| 	u8	etags[MT7530_NUM_VLANS]; | ||||
| 	u16	vids[MT7530_NUM_VLANS]; | ||||
| } mt7530_defaults[] = { | ||||
| 	{ | ||||
| 		.name = "llllw", | ||||
| 		.pvids = { 1, 1, 1, 1, 2, 1, 1 }, | ||||
| 		.members = { 0, 0x6f, 0x50 }, | ||||
| 		.etags = { 0, 0x40, 0x40 }, | ||||
| 		.vids = { 0, 1, 2 }, | ||||
| 	}, { | ||||
| 		.name = "wllll", | ||||
| 		.pvids = { 2, 1, 1, 1, 1, 1, 1 }, | ||||
| 		.members = { 0, 0x7e, 0x41 }, | ||||
| 		.etags = { 0, 0x40, 0x40 }, | ||||
| 		.vids = { 0, 1, 2 }, | ||||
| 	}, | ||||
| }; | ||||
|  | ||||
| struct mt7530_mapping* | ||||
| mt7530_find_mapping(struct device_node *np) | ||||
| { | ||||
| 	const char *map; | ||||
| 	int i; | ||||
|  | ||||
| 	if (of_property_read_string(np, "mediatek,portmap", &map)) | ||||
| 		return NULL; | ||||
|  | ||||
| 	for (i = 0; i < ARRAY_SIZE(mt7530_defaults); i++) | ||||
| 		if (!strcmp(map, mt7530_defaults[i].name)) | ||||
| 			return &mt7530_defaults[i]; | ||||
|  | ||||
| 	return NULL; | ||||
| } | ||||
|  | ||||
| static void | ||||
| mt7530_apply_mapping(struct mt7530_priv *mt7530, struct mt7530_mapping *map) | ||||
| { | ||||
| 	int i = 0; | ||||
|  | ||||
| 	for (i = 0; i < MT7530_NUM_PORTS; i++) | ||||
| 		mt7530->port_entries[i].pvid = map->pvids[i]; | ||||
|  | ||||
| 	for (i = 0; i < MT7530_NUM_VLANS; i++) { | ||||
| 		mt7530->vlan_entries[i].member = map->members[i]; | ||||
| 		mt7530->vlan_entries[i].etags = map->etags[i]; | ||||
| 		mt7530->vlan_entries[i].vid = map->vids[i]; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static int | ||||
| mt7530_reset_switch(struct switch_dev *dev) | ||||
| { | ||||
| 	struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); | ||||
| 	int i; | ||||
|  | ||||
| 	memset(priv->port_entries, 0, sizeof(priv->port_entries)); | ||||
| 	memset(priv->vlan_entries, 0, sizeof(priv->vlan_entries)); | ||||
|  | ||||
| 	/* set default vid of each vlan to the same number of vlan, so the vid | ||||
| 	 * won't need be set explicitly. | ||||
| 	 */ | ||||
| 	for (i = 0; i < MT7530_NUM_VLANS; i++) { | ||||
| 		priv->vlan_entries[i].vid = i; | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int | ||||
| mt7530_get_vlan_enable(struct switch_dev *dev, | ||||
| 			   const struct switch_attr *attr, | ||||
| 			   struct switch_val *val) | ||||
| { | ||||
| 	struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); | ||||
|  | ||||
| 	val->value.i = priv->global_vlan_enable; | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int | ||||
| mt7530_set_vlan_enable(struct switch_dev *dev, | ||||
| 			   const struct switch_attr *attr, | ||||
| 			   struct switch_val *val) | ||||
| { | ||||
| 	struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); | ||||
|  | ||||
| 	priv->global_vlan_enable = val->value.i != 0; | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static u32 | ||||
| mt7530_r32(struct mt7530_priv *priv, u32 reg) | ||||
| { | ||||
| 	u32 val; | ||||
| 	if (priv->bus) { | ||||
| 		u16 high, low; | ||||
|  | ||||
| 		mdiobus_write(priv->bus, 0x1f, 0x1f, (reg >> 6) & 0x3ff); | ||||
| 		low = mdiobus_read(priv->bus, 0x1f, (reg >> 2) & 0xf); | ||||
| 		high = mdiobus_read(priv->bus, 0x1f, 0x10); | ||||
|  | ||||
| 		return (high << 16) | (low & 0xffff); | ||||
| 	} | ||||
|  | ||||
| 	val = ioread32(priv->base + reg); | ||||
| 	pr_debug("MT7530 MDIO Read [%04x]=%08x\n", reg, val); | ||||
|  | ||||
| 	return val; | ||||
| } | ||||
|  | ||||
| static void | ||||
| mt7530_w32(struct mt7530_priv *priv, u32 reg, u32 val) | ||||
| { | ||||
| 	if (priv->bus) { | ||||
| 		mdiobus_write(priv->bus, 0x1f, 0x1f, (reg >> 6) & 0x3ff); | ||||
| 		mdiobus_write(priv->bus, 0x1f, (reg >> 2) & 0xf,  val & 0xffff); | ||||
| 		mdiobus_write(priv->bus, 0x1f, 0x10, val >> 16); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	pr_debug("MT7530 MDIO Write[%04x]=%08x\n", reg, val); | ||||
| 	iowrite32(val, priv->base + reg); | ||||
| } | ||||
|  | ||||
| static void | ||||
| mt7530_vtcr(struct mt7530_priv *priv, u32 cmd, u32 val) | ||||
| { | ||||
| 	int i; | ||||
|  | ||||
| 	mt7530_w32(priv, REG_ESW_VLAN_VTCR, BIT(31) | (cmd << 12) | val); | ||||
|  | ||||
| 	for (i = 0; i < 20; i++) { | ||||
| 		u32 val = mt7530_r32(priv, REG_ESW_VLAN_VTCR); | ||||
|  | ||||
| 		if ((val & BIT(31)) == 0) | ||||
| 			break; | ||||
|  | ||||
| 		udelay(1000); | ||||
| 	} | ||||
| 	if (i == 20) | ||||
| 		printk("mt7530: vtcr timeout\n"); | ||||
| } | ||||
|  | ||||
| static int | ||||
| mt7530_get_port_pvid(struct switch_dev *dev, int port, int *val) | ||||
| { | ||||
| 	struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); | ||||
|  | ||||
| 	if (port >= MT7530_NUM_PORTS) | ||||
| 		return -EINVAL; | ||||
|  | ||||
| 	*val = mt7530_r32(priv, REG_ESW_PORT_PPBV1(port)); | ||||
| 	*val &= 0xfff; | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int | ||||
| mt7530_set_port_pvid(struct switch_dev *dev, int port, int pvid) | ||||
| { | ||||
| 	struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); | ||||
|  | ||||
| 	if (port >= MT7530_NUM_PORTS) | ||||
| 		return -EINVAL; | ||||
|  | ||||
| 	if (pvid < MT7530_MIN_VID || pvid > MT7530_MAX_VID) | ||||
| 		return -EINVAL; | ||||
|  | ||||
| 	priv->port_entries[port].pvid = pvid; | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int | ||||
| mt7530_get_vlan_ports(struct switch_dev *dev, struct switch_val *val) | ||||
| { | ||||
| 	struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); | ||||
| 	u32 member; | ||||
| 	u32 etags; | ||||
| 	int i; | ||||
|  | ||||
| 	val->len = 0; | ||||
|  | ||||
| 	if (val->port_vlan < 0 || val->port_vlan >= MT7530_NUM_VLANS) | ||||
| 		return -EINVAL; | ||||
|  | ||||
| 	mt7530_vtcr(priv, 0, val->port_vlan); | ||||
|  | ||||
| 	member = mt7530_r32(priv, REG_ESW_VLAN_VAWD1); | ||||
| 	member >>= 16; | ||||
| 	member &= 0xff; | ||||
|  | ||||
| 	etags = mt7530_r32(priv, REG_ESW_VLAN_VAWD2); | ||||
|  | ||||
| 	for (i = 0; i < MT7530_NUM_PORTS; i++) { | ||||
| 		struct switch_port *p; | ||||
| 		int etag; | ||||
|  | ||||
| 		if (!(member & BIT(i))) | ||||
| 			continue; | ||||
|  | ||||
| 		p = &val->value.ports[val->len++]; | ||||
| 		p->id = i; | ||||
|  | ||||
| 		etag = (etags >> (i * 2)) & 0x3; | ||||
|  | ||||
| 		if (etag == ETAG_CTRL_TAG) | ||||
| 			p->flags |= BIT(SWITCH_PORT_FLAG_TAGGED); | ||||
| 		else if (etag != ETAG_CTRL_UNTAG) | ||||
| 			printk("vlan egress tag control neither untag nor tag.\n"); | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int | ||||
| mt7530_set_vlan_ports(struct switch_dev *dev, struct switch_val *val) | ||||
| { | ||||
| 	struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); | ||||
| 	u8 member = 0; | ||||
| 	u8 etags = 0; | ||||
| 	int i; | ||||
|  | ||||
| 	if (val->port_vlan < 0 || val->port_vlan >= MT7530_NUM_VLANS || | ||||
| 			val->len > MT7530_NUM_PORTS) | ||||
| 		return -EINVAL; | ||||
|  | ||||
| 	for (i = 0; i < val->len; i++) { | ||||
| 		struct switch_port *p = &val->value.ports[i]; | ||||
|  | ||||
| 		if (p->id >= MT7530_NUM_PORTS) | ||||
| 			return -EINVAL; | ||||
|  | ||||
| 		member |= BIT(p->id); | ||||
|  | ||||
| 		if (p->flags & BIT(SWITCH_PORT_FLAG_TAGGED)) | ||||
| 			etags |= BIT(p->id); | ||||
| 	} | ||||
| 	priv->vlan_entries[val->port_vlan].member = member; | ||||
| 	priv->vlan_entries[val->port_vlan].etags = etags; | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int | ||||
| mt7530_set_vid(struct switch_dev *dev, const struct switch_attr *attr, | ||||
| 		struct switch_val *val) | ||||
| { | ||||
| 	struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); | ||||
| 	int vlan; | ||||
| 	u16 vid; | ||||
|  | ||||
| 	vlan = val->port_vlan; | ||||
| 	vid = (u16)val->value.i; | ||||
|  | ||||
| 	if (vlan < 0 || vlan >= MT7530_NUM_VLANS) | ||||
| 		return -EINVAL; | ||||
|  | ||||
| 	if (vid < MT7530_MIN_VID || vid > MT7530_MAX_VID) | ||||
| 		return -EINVAL; | ||||
|  | ||||
| 	priv->vlan_entries[vlan].vid = vid; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int | ||||
| mt7530_get_vid(struct switch_dev *dev, const struct switch_attr *attr, | ||||
| 		struct switch_val *val) | ||||
| { | ||||
| 	struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); | ||||
| 	u32 vid; | ||||
| 	int vlan; | ||||
|  | ||||
| 	vlan = val->port_vlan; | ||||
|  | ||||
| 	vid = mt7530_r32(priv, REG_ESW_VLAN_VTIM(vlan)); | ||||
| 	if (vlan & 1) | ||||
| 		vid = vid >> 12; | ||||
| 	vid &= 0xfff; | ||||
|  | ||||
| 	val->value.i = vid; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int | ||||
| mt7530_apply_config(struct switch_dev *dev) | ||||
| { | ||||
| 	struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); | ||||
| 	int i, j; | ||||
| 	u8 tag_ports; | ||||
| 	u8 untag_ports; | ||||
|  | ||||
| 	if (!priv->global_vlan_enable) { | ||||
| 		for (i = 0; i < MT7530_NUM_PORTS; i++) | ||||
| 			mt7530_w32(priv, REG_ESW_PORT_PCR(i), 0x00400000); | ||||
|  | ||||
| 		mt7530_w32(priv, REG_ESW_PORT_PCR(MT7530_CPU_PORT), 0x00ff0000); | ||||
|  | ||||
| 		for (i = 0; i < MT7530_NUM_PORTS; i++) | ||||
| 			mt7530_w32(priv, REG_ESW_PORT_PVC(i), 0x810000c0); | ||||
|  | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	/* set all ports as security mode */ | ||||
| 	for (i = 0; i < MT7530_NUM_PORTS; i++) | ||||
| 		mt7530_w32(priv, REG_ESW_PORT_PCR(i), 0x00ff0003); | ||||
|  | ||||
| 	/* check if a port is used in tag/untag vlan egress mode */ | ||||
| 	tag_ports = 0; | ||||
| 	untag_ports = 0; | ||||
|  | ||||
| 	for (i = 0; i < MT7530_NUM_VLANS; i++) { | ||||
| 		u8 member = priv->vlan_entries[i].member; | ||||
| 		u8 etags = priv->vlan_entries[i].etags; | ||||
|  | ||||
| 		if (!member) | ||||
| 			continue; | ||||
|  | ||||
| 		for (j = 0; j < MT7530_NUM_PORTS; j++) { | ||||
| 			if (!(member & BIT(j))) | ||||
| 				continue; | ||||
|  | ||||
| 			if (etags & BIT(j)) | ||||
| 				tag_ports |= 1u << j; | ||||
| 			else | ||||
| 				untag_ports |= 1u << j; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	/* set all untag-only ports as transparent and the rest as user port */ | ||||
| 	for (i = 0; i < MT7530_NUM_PORTS; i++) { | ||||
| 		u32 pvc_mode = 0x81000000; | ||||
|  | ||||
| 		if (untag_ports & BIT(i) && !(tag_ports & BIT(i))) | ||||
| 			pvc_mode = 0x810000c0; | ||||
|  | ||||
| 		mt7530_w32(priv, REG_ESW_PORT_PVC(i), pvc_mode); | ||||
| 	} | ||||
|  | ||||
| 	for (i = 0; i < MT7530_NUM_VLANS; i++) { | ||||
| 		u16 vid = priv->vlan_entries[i].vid; | ||||
| 		u8 member = priv->vlan_entries[i].member; | ||||
| 		u8 etags = priv->vlan_entries[i].etags; | ||||
| 		u32 val; | ||||
|  | ||||
| #ifndef CONFIG_SOC_MT7621 | ||||
| 		/* vid of vlan */ | ||||
| 		val = mt7530_r32(priv, REG_ESW_VLAN_VTIM(i)); | ||||
| 		if (i % 2 == 0) { | ||||
| 			val &= 0xfff000; | ||||
| 			val |= vid; | ||||
| 		} else { | ||||
| 			val &= 0xfff; | ||||
| 			val |= (vid << 12); | ||||
| 		} | ||||
| 		mt7530_w32(priv, REG_ESW_VLAN_VTIM(i), val); | ||||
| #endif | ||||
| 		/* vlan port membership */ | ||||
| 		if (member) | ||||
| 			mt7530_w32(priv, REG_ESW_VLAN_VAWD1, REG_ESW_VLAN_VAWD1_IVL_MAC | | ||||
| 				REG_ESW_VLAN_VAWD1_VTAG_EN | (member << 16) | | ||||
| 				REG_ESW_VLAN_VAWD1_VALID); | ||||
| 		else | ||||
| 			mt7530_w32(priv, REG_ESW_VLAN_VAWD1, 0); | ||||
|  | ||||
| 		/* egress mode */ | ||||
| 		val = 0; | ||||
| 		for (j = 0; j < MT7530_NUM_PORTS; j++) { | ||||
| 			if (etags & BIT(j)) | ||||
| 				val |= ETAG_CTRL_TAG << (j * 2); | ||||
| 			else | ||||
| 				val |= ETAG_CTRL_UNTAG << (j * 2); | ||||
| 		} | ||||
| 		mt7530_w32(priv, REG_ESW_VLAN_VAWD2, val); | ||||
|  | ||||
| 		/* write to vlan table */ | ||||
| #ifdef CONFIG_SOC_MT7621 | ||||
| 		mt7530_vtcr(priv, 1, vid); | ||||
| #else | ||||
| 		mt7530_vtcr(priv, 1, i); | ||||
| #endif | ||||
| 	} | ||||
|  | ||||
| 	/* Port Default PVID */ | ||||
| 	for (i = 0; i < MT7530_NUM_PORTS; i++) { | ||||
| 		u32 val; | ||||
| 		val = mt7530_r32(priv, REG_ESW_PORT_PPBV1(i)); | ||||
| 		val &= ~0xfff; | ||||
| 		val |= priv->port_entries[i].pvid; | ||||
| 		mt7530_w32(priv, REG_ESW_PORT_PPBV1(i), val); | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int | ||||
| mt7530_get_port_link(struct switch_dev *dev,  int port, | ||||
| 			struct switch_port_link *link) | ||||
| { | ||||
| 	struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); | ||||
| 	u32 speed, pmsr; | ||||
|  | ||||
| 	if (port < 0 || port >= MT7530_NUM_PORTS) | ||||
| 		return -EINVAL; | ||||
|  | ||||
| 	pmsr = mt7530_r32(priv, 0x3008 + (0x100 * port)); | ||||
|  | ||||
| 	link->link = pmsr & 1; | ||||
| 	link->duplex = (pmsr >> 1) & 1; | ||||
| 	speed = (pmsr >> 2) & 3; | ||||
|  | ||||
| 	switch (speed) { | ||||
| 	case 0: | ||||
| 		link->speed = SWITCH_PORT_SPEED_10; | ||||
| 		break; | ||||
| 	case 1: | ||||
| 		link->speed = SWITCH_PORT_SPEED_100; | ||||
| 		break; | ||||
| 	case 2: | ||||
| 	case 3: /* forced gige speed can be 2 or 3 */ | ||||
| 		link->speed = SWITCH_PORT_SPEED_1000; | ||||
| 		break; | ||||
| 	default: | ||||
| 		link->speed = SWITCH_PORT_SPEED_UNKNOWN; | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static u64 get_mib_counter(struct mt7530_priv *priv, int i, int port) | ||||
| { | ||||
| 	unsigned int port_base; | ||||
| 	u64 lo; | ||||
|  | ||||
| 	port_base = MT7621_MIB_COUNTER_BASE + | ||||
| 		    MT7621_MIB_COUNTER_PORT_OFFSET * port; | ||||
|  | ||||
| 	lo = mt7530_r32(priv, port_base + mt7621_mibs[i].offset); | ||||
| 	if (mt7621_mibs[i].size == 2) { | ||||
| 		u64 hi; | ||||
|  | ||||
| 		hi = mt7530_r32(priv, port_base + mt7621_mibs[i].offset + 4); | ||||
| 		lo |= hi << 32; | ||||
| 	} | ||||
|  | ||||
| 	return lo; | ||||
| } | ||||
|  | ||||
| static int mt7621_sw_get_port_mib(struct switch_dev *dev, | ||||
| 				  const struct switch_attr *attr, | ||||
| 				  struct switch_val *val) | ||||
| { | ||||
| 	static char buf[4096]; | ||||
| 	struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); | ||||
| 	int i, len = 0; | ||||
|  | ||||
| 	if (val->port_vlan >= MT7530_NUM_PORTS) | ||||
| 		return -EINVAL; | ||||
|  | ||||
| 	len += snprintf(buf + len, sizeof(buf) - len, | ||||
| 			"Port %d MIB counters\n", val->port_vlan); | ||||
|  | ||||
| 	for (i = 0; i < ARRAY_SIZE(mt7621_mibs); ++i) { | ||||
| 		u64 counter; | ||||
| 		len += snprintf(buf + len, sizeof(buf) - len, | ||||
| 				"%-11s: ", mt7621_mibs[i].name); | ||||
| 		counter = get_mib_counter(priv, i, val->port_vlan); | ||||
| 		len += snprintf(buf + len, sizeof(buf) - len, "%llu\n", | ||||
| 				counter); | ||||
| 	} | ||||
|  | ||||
| 	val->value.s = buf; | ||||
| 	val->len = len; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static u64 get_mib_counter_7620(struct mt7530_priv *priv, int i) | ||||
| { | ||||
| 	return mt7530_r32(priv, MT7620_MIB_COUNTER_BASE + mt7620_mibs[i].offset); | ||||
| } | ||||
|  | ||||
| static u64 get_mib_counter_port_7620(struct mt7530_priv *priv, int i, int port) | ||||
| { | ||||
| 	return mt7530_r32(priv, | ||||
| 			MT7620_MIB_COUNTER_BASE_PORT + | ||||
| 			(MT7620_MIB_COUNTER_PORT_OFFSET * port) + | ||||
| 			mt7620_port_mibs[i].offset); | ||||
| } | ||||
|  | ||||
| static int mt7530_sw_get_mib(struct switch_dev *dev, | ||||
| 				  const struct switch_attr *attr, | ||||
| 				  struct switch_val *val) | ||||
| { | ||||
| 	static char buf[4096]; | ||||
| 	struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); | ||||
| 	int i, len = 0; | ||||
|  | ||||
| 	len += snprintf(buf + len, sizeof(buf) - len, "Switch MIB counters\n"); | ||||
|  | ||||
| 	for (i = 0; i < ARRAY_SIZE(mt7620_mibs); ++i) { | ||||
| 		u64 counter; | ||||
| 		len += snprintf(buf + len, sizeof(buf) - len, | ||||
| 				"%-11s: ", mt7620_mibs[i].name); | ||||
| 		counter = get_mib_counter_7620(priv, i); | ||||
| 		len += snprintf(buf + len, sizeof(buf) - len, "%llu\n", | ||||
| 				counter); | ||||
| 	} | ||||
|  | ||||
| 	val->value.s = buf; | ||||
| 	val->len = len; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static int mt7530_sw_get_port_mib(struct switch_dev *dev, | ||||
| 				  const struct switch_attr *attr, | ||||
| 				  struct switch_val *val) | ||||
| { | ||||
| 	static char buf[4096]; | ||||
| 	struct mt7530_priv *priv = container_of(dev, struct mt7530_priv, swdev); | ||||
| 	int i, len = 0; | ||||
|  | ||||
| 	if (val->port_vlan >= MT7530_NUM_PORTS) | ||||
| 		return -EINVAL; | ||||
|  | ||||
| 	len += snprintf(buf + len, sizeof(buf) - len, | ||||
| 			"Port %d MIB counters\n", val->port_vlan); | ||||
|  | ||||
| 	for (i = 0; i < ARRAY_SIZE(mt7620_port_mibs); ++i) { | ||||
| 		u64 counter; | ||||
| 		len += snprintf(buf + len, sizeof(buf) - len, | ||||
| 				"%-11s: ", mt7620_port_mibs[i].name); | ||||
| 		counter = get_mib_counter_port_7620(priv, i, val->port_vlan); | ||||
| 		len += snprintf(buf + len, sizeof(buf) - len, "%llu\n", | ||||
| 				counter); | ||||
| 	} | ||||
|  | ||||
| 	val->value.s = buf; | ||||
| 	val->len = len; | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static const struct switch_attr mt7530_global[] = { | ||||
| 	{ | ||||
| 		.type = SWITCH_TYPE_INT, | ||||
| 		.name = "enable_vlan", | ||||
| 		.description = "VLAN mode (1:enabled)", | ||||
| 		.max = 1, | ||||
| 		.id = MT7530_ATTR_ENABLE_VLAN, | ||||
| 		.get = mt7530_get_vlan_enable, | ||||
| 		.set = mt7530_set_vlan_enable, | ||||
| 	}, { | ||||
| 		.type = SWITCH_TYPE_STRING, | ||||
| 		.name = "mib", | ||||
| 		.description = "Get MIB counters for switch", | ||||
| 		.get = mt7530_sw_get_mib, | ||||
| 		.set = NULL, | ||||
| 	}, | ||||
| }; | ||||
|  | ||||
| static const struct switch_attr mt7621_port[] = { | ||||
| 	{ | ||||
| 		.type = SWITCH_TYPE_STRING, | ||||
| 		.name = "mib", | ||||
| 		.description = "Get MIB counters for port", | ||||
| 		.get = mt7621_sw_get_port_mib, | ||||
| 		.set = NULL, | ||||
| 	}, | ||||
| }; | ||||
|  | ||||
| static const struct switch_attr mt7530_port[] = { | ||||
| 	{ | ||||
| 		.type = SWITCH_TYPE_STRING, | ||||
| 		.name = "mib", | ||||
| 		.description = "Get MIB counters for port", | ||||
| 		.get = mt7530_sw_get_port_mib, | ||||
| 		.set = NULL, | ||||
| 	}, | ||||
| }; | ||||
|  | ||||
| static const struct switch_attr mt7530_vlan[] = { | ||||
| 	{ | ||||
| 		.type = SWITCH_TYPE_INT, | ||||
| 		.name = "vid", | ||||
| 		.description = "VLAN ID (0-4094)", | ||||
| 		.set = mt7530_set_vid, | ||||
| 		.get = mt7530_get_vid, | ||||
| 		.max = 4094, | ||||
| 	}, | ||||
| }; | ||||
|  | ||||
| static const struct switch_dev_ops mt7621_ops = { | ||||
| 	.attr_global = { | ||||
| 		.attr = mt7530_global, | ||||
| 		.n_attr = ARRAY_SIZE(mt7530_global), | ||||
| 	}, | ||||
| 	.attr_port = { | ||||
| 		.attr = mt7621_port, | ||||
| 		.n_attr = ARRAY_SIZE(mt7621_port), | ||||
| 	}, | ||||
| 	.attr_vlan = { | ||||
| 		.attr = mt7530_vlan, | ||||
| 		.n_attr = ARRAY_SIZE(mt7530_vlan), | ||||
| 	}, | ||||
| 	.get_vlan_ports = mt7530_get_vlan_ports, | ||||
| 	.set_vlan_ports = mt7530_set_vlan_ports, | ||||
| 	.get_port_pvid = mt7530_get_port_pvid, | ||||
| 	.set_port_pvid = mt7530_set_port_pvid, | ||||
| 	.get_port_link = mt7530_get_port_link, | ||||
| 	.apply_config = mt7530_apply_config, | ||||
| 	.reset_switch = mt7530_reset_switch, | ||||
| }; | ||||
|  | ||||
| static const struct switch_dev_ops mt7530_ops = { | ||||
| 	.attr_global = { | ||||
| 		.attr = mt7530_global, | ||||
| 		.n_attr = ARRAY_SIZE(mt7530_global), | ||||
| 	}, | ||||
| 	.attr_port = { | ||||
| 		.attr = mt7530_port, | ||||
| 		.n_attr = ARRAY_SIZE(mt7530_port), | ||||
| 	}, | ||||
| 	.attr_vlan = { | ||||
| 		.attr = mt7530_vlan, | ||||
| 		.n_attr = ARRAY_SIZE(mt7530_vlan), | ||||
| 	}, | ||||
| 	.get_vlan_ports = mt7530_get_vlan_ports, | ||||
| 	.set_vlan_ports = mt7530_set_vlan_ports, | ||||
| 	.get_port_pvid = mt7530_get_port_pvid, | ||||
| 	.set_port_pvid = mt7530_set_port_pvid, | ||||
| 	.get_port_link = mt7530_get_port_link, | ||||
| 	.apply_config = mt7530_apply_config, | ||||
| 	.reset_switch = mt7530_reset_switch, | ||||
| }; | ||||
|  | ||||
| int | ||||
| mt7530_probe(struct device *dev, void __iomem *base, struct mii_bus *bus, int vlan) | ||||
| { | ||||
| 	struct switch_dev *swdev; | ||||
| 	struct mt7530_priv *mt7530; | ||||
| 	struct mt7530_mapping *map; | ||||
| 	int ret; | ||||
|  | ||||
| 	mt7530 = devm_kzalloc(dev, sizeof(struct mt7530_priv), GFP_KERNEL); | ||||
| 	if (!mt7530) | ||||
| 		return -ENOMEM; | ||||
|  | ||||
| 	mt7530->base = base; | ||||
| 	mt7530->bus = bus; | ||||
| 	mt7530->global_vlan_enable = vlan; | ||||
|  | ||||
| 	swdev = &mt7530->swdev; | ||||
| 	if (bus) { | ||||
| 		swdev->alias = "mt7530"; | ||||
| 		swdev->name = "mt7530"; | ||||
| 	} else if (IS_ENABLED(CONFIG_SOC_MT7621)) { | ||||
| 		swdev->alias = "mt7621"; | ||||
| 		swdev->name = "mt7621"; | ||||
| 	} else { | ||||
| 		swdev->alias = "mt7620"; | ||||
| 		swdev->name = "mt7620"; | ||||
| 	} | ||||
| 	swdev->cpu_port = MT7530_CPU_PORT; | ||||
| 	swdev->ports = MT7530_NUM_PORTS; | ||||
| 	swdev->vlans = MT7530_NUM_VLANS; | ||||
| 	if (IS_ENABLED(CONFIG_SOC_MT7621)) | ||||
| 		swdev->ops = &mt7621_ops; | ||||
| 	else | ||||
| 		swdev->ops = &mt7530_ops; | ||||
|  | ||||
| 	ret = register_switch(swdev, NULL); | ||||
| 	if (ret) { | ||||
| 		dev_err(dev, "failed to register mt7530\n"); | ||||
| 		return ret; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	map = mt7530_find_mapping(dev->of_node); | ||||
| 	if (map) | ||||
| 		mt7530_apply_mapping(mt7530, map); | ||||
| 	mt7530_apply_config(swdev); | ||||
|  | ||||
| 	/* magic vodoo */ | ||||
| 	if (!IS_ENABLED(CONFIG_SOC_MT7621) && bus && mt7530_r32(mt7530, REG_HWTRAP) !=  0x1117edf) { | ||||
| 	        dev_info(dev, "fixing up MHWTRAP register - bootloader probably played with it\n"); | ||||
| 		mt7530_w32(mt7530, REG_HWTRAP, 0x1117edf); | ||||
| 	} | ||||
| 	dev_info(dev, "loaded %s driver\n", swdev->name); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
							
								
								
									
										186
									
								
								target/linux/ramips/files-4.9/drivers/net/ethernet/mtk/mt7530.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										186
									
								
								target/linux/ramips/files-4.9/drivers/net/ethernet/mtk/mt7530.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,186 @@ | ||||
| /* | ||||
|  * 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 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. | ||||
|  * | ||||
|  * Copyright (C) 2013 John Crispin <blogic@openwrt.org> | ||||
|  * Copyright (C) 2016 Vitaly Chekryzhev <13hakta@gmail.com> | ||||
|  */ | ||||
|  | ||||
| #ifndef _MT7530_H__ | ||||
| #define _MT7530_H__ | ||||
|  | ||||
| #define MT7620_MIB_COUNTER_BASE_PORT	0x4000 | ||||
| #define MT7620_MIB_COUNTER_PORT_OFFSET	0x100 | ||||
| #define MT7620_MIB_COUNTER_BASE	0x1010 | ||||
|  | ||||
| /* PPE Accounting Group #0 Byte Counter */ | ||||
| #define MT7620_MIB_STATS_PPE_AC_BCNT0	0x000 | ||||
|  | ||||
| /* PPE Accounting Group #0 Packet Counter */ | ||||
| #define MT7620_MIB_STATS_PPE_AC_PCNT0	0x004 | ||||
|  | ||||
| /* PPE Accounting Group #63 Byte Counter */ | ||||
| #define MT7620_MIB_STATS_PPE_AC_BCNT63	0x1F8 | ||||
|  | ||||
| /* PPE Accounting Group #63 Packet Counter */ | ||||
| #define MT7620_MIB_STATS_PPE_AC_PCNT63	0x1FC | ||||
|  | ||||
| /* PPE Meter Group #0 */ | ||||
| #define MT7620_MIB_STATS_PPE_MTR_CNT0	0x200 | ||||
|  | ||||
| /* PPE Meter Group #63 */ | ||||
| #define MT7620_MIB_STATS_PPE_MTR_CNT63	0x2FC | ||||
|  | ||||
| /* Transmit good byte count for CPU GDM */ | ||||
| #define MT7620_MIB_STATS_GDM1_TX_GBCNT	0x300 | ||||
|  | ||||
| /* Transmit good packet count for CPU GDM (exclude flow control frames) */ | ||||
| #define MT7620_MIB_STATS_GDM1_TX_GPCNT	0x304 | ||||
|  | ||||
| /* Transmit abort count for CPU GDM */ | ||||
| #define MT7620_MIB_STATS_GDM1_TX_SKIPCNT	0x308 | ||||
|  | ||||
| /* Transmit collision count for CPU GDM */ | ||||
| #define MT7620_MIB_STATS_GDM1_TX_COLCNT	0x30C | ||||
|  | ||||
| /* Received good byte count for CPU GDM */ | ||||
| #define MT7620_MIB_STATS_GDM1_RX_GBCNT1	0x320 | ||||
|  | ||||
| /* Received good packet count for CPU GDM (exclude flow control frame) */ | ||||
| #define MT7620_MIB_STATS_GDM1_RX_GPCNT1	0x324 | ||||
|  | ||||
| /* Received overflow error packet count for CPU GDM */ | ||||
| #define MT7620_MIB_STATS_GDM1_RX_OERCNT	0x328 | ||||
|  | ||||
| /* Received FCS error packet count for CPU GDM */ | ||||
| #define MT7620_MIB_STATS_GDM1_RX_FERCNT	0x32C | ||||
|  | ||||
| /* Received too short error packet count for CPU GDM */ | ||||
| #define MT7620_MIB_STATS_GDM1_RX_SERCNT	0x330 | ||||
|  | ||||
| /* Received too long error packet count for CPU GDM */ | ||||
| #define MT7620_MIB_STATS_GDM1_RX_LERCNT	0x334 | ||||
|  | ||||
| /* Received IP/TCP/UDP checksum error packet count for CPU GDM */ | ||||
| #define MT7620_MIB_STATS_GDM1_RX_CERCNT	0x338 | ||||
|  | ||||
| /* Received flow control pkt count for CPU GDM */ | ||||
| #define MT7620_MIB_STATS_GDM1_RX_FCCNT	0x33C | ||||
|  | ||||
| /* Transmit good byte count for PPE GDM */ | ||||
| #define MT7620_MIB_STATS_GDM2_TX_GBCNT	0x340 | ||||
|  | ||||
| /* Transmit good packet count for PPE GDM (exclude flow control frames) */ | ||||
| #define MT7620_MIB_STATS_GDM2_TX_GPCNT	0x344 | ||||
|  | ||||
| /* Transmit abort count for PPE GDM */ | ||||
| #define MT7620_MIB_STATS_GDM2_TX_SKIPCNT	0x348 | ||||
|  | ||||
| /* Transmit collision count for PPE GDM */ | ||||
| #define MT7620_MIB_STATS_GDM2_TX_COLCNT	0x34C | ||||
|  | ||||
| /* Received good byte count for PPE GDM */ | ||||
| #define MT7620_MIB_STATS_GDM2_RX_GBCNT	0x360 | ||||
|  | ||||
| /* Received good packet count for PPE GDM (exclude flow control frame) */ | ||||
| #define MT7620_MIB_STATS_GDM2_RX_GPCNT	0x364 | ||||
|  | ||||
| /* Received overflow error packet count for PPE GDM */ | ||||
| #define MT7620_MIB_STATS_GDM2_RX_OERCNT	0x368 | ||||
|  | ||||
| /* Received FCS error packet count for PPE GDM */ | ||||
| #define MT7620_MIB_STATS_GDM2_RX_FERCNT	0x36C | ||||
|  | ||||
| /* Received too short error packet count for PPE GDM */ | ||||
| #define MT7620_MIB_STATS_GDM2_RX_SERCNT	0x370 | ||||
|  | ||||
| /* Received too long error packet count for PPE GDM */ | ||||
| #define MT7620_MIB_STATS_GDM2_RX_LERCNT	0x374 | ||||
|  | ||||
| /* Received IP/TCP/UDP checksum error packet count for PPE GDM */ | ||||
| #define MT7620_MIB_STATS_GDM2_RX_CERCNT	0x378 | ||||
|  | ||||
| /* Received flow control pkt count for PPE GDM */ | ||||
| #define MT7620_MIB_STATS_GDM2_RX_FCCNT	0x37C | ||||
|  | ||||
| /* Tx Packet Counter of Port n */ | ||||
| #define MT7620_MIB_STATS_PORT_TGPCN	0x10 | ||||
|  | ||||
| /* Tx Bad Octet Counter of Port n */ | ||||
| #define MT7620_MIB_STATS_PORT_TBOCN	0x14 | ||||
|  | ||||
| /* Tx Good Octet Counter of Port n */ | ||||
| #define MT7620_MIB_STATS_PORT_TGOCN	0x18 | ||||
|  | ||||
| /* Tx Event Packet Counter of Port n */ | ||||
| #define MT7620_MIB_STATS_PORT_TEPCN	0x1C | ||||
|  | ||||
| /* Rx Packet Counter of Port n */ | ||||
| #define MT7620_MIB_STATS_PORT_RGPCN	0x20 | ||||
|  | ||||
| /* Rx Bad Octet Counter of Port n */ | ||||
| #define MT7620_MIB_STATS_PORT_RBOCN	0x24 | ||||
|  | ||||
| /* Rx Good Octet Counter of Port n */ | ||||
| #define MT7620_MIB_STATS_PORT_RGOCN	0x28 | ||||
|  | ||||
| /* Rx Event Packet Counter of Port n */ | ||||
| #define MT7620_MIB_STATS_PORT_REPC1N	0x2C | ||||
|  | ||||
| /* Rx Event Packet Counter of Port n */ | ||||
| #define MT7620_MIB_STATS_PORT_REPC2N	0x30 | ||||
|  | ||||
| #define MT7621_MIB_COUNTER_BASE	0x4000 | ||||
| #define MT7621_MIB_COUNTER_PORT_OFFSET	0x100 | ||||
| #define MT7621_STATS_TDPC	0x00 | ||||
| #define MT7621_STATS_TCRC	0x04 | ||||
| #define MT7621_STATS_TUPC	0x08 | ||||
| #define MT7621_STATS_TMPC	0x0C | ||||
| #define MT7621_STATS_TBPC	0x10 | ||||
| #define MT7621_STATS_TCEC	0x14 | ||||
| #define MT7621_STATS_TSCEC	0x18 | ||||
| #define MT7621_STATS_TMCEC	0x1C | ||||
| #define MT7621_STATS_TDEC	0x20 | ||||
| #define MT7621_STATS_TLCEC	0x24 | ||||
| #define MT7621_STATS_TXCEC	0x28 | ||||
| #define MT7621_STATS_TPPC	0x2C | ||||
| #define MT7621_STATS_TL64PC	0x30 | ||||
| #define MT7621_STATS_TL65PC	0x34 | ||||
| #define MT7621_STATS_TL128PC	0x38 | ||||
| #define MT7621_STATS_TL256PC	0x3C | ||||
| #define MT7621_STATS_TL512PC	0x40 | ||||
| #define MT7621_STATS_TL1024PC	0x44 | ||||
| #define MT7621_STATS_TOC	0x48 | ||||
| #define MT7621_STATS_RDPC	0x60 | ||||
| #define MT7621_STATS_RFPC	0x64 | ||||
| #define MT7621_STATS_RUPC	0x68 | ||||
| #define MT7621_STATS_RMPC	0x6C | ||||
| #define MT7621_STATS_RBPC	0x70 | ||||
| #define MT7621_STATS_RAEPC	0x74 | ||||
| #define MT7621_STATS_RCEPC	0x78 | ||||
| #define MT7621_STATS_RUSPC	0x7C | ||||
| #define MT7621_STATS_RFEPC	0x80 | ||||
| #define MT7621_STATS_ROSPC	0x84 | ||||
| #define MT7621_STATS_RJEPC	0x88 | ||||
| #define MT7621_STATS_RPPC	0x8C | ||||
| #define MT7621_STATS_RL64PC	0x90 | ||||
| #define MT7621_STATS_RL65PC	0x94 | ||||
| #define MT7621_STATS_RL128PC	0x98 | ||||
| #define MT7621_STATS_RL256PC	0x9C | ||||
| #define MT7621_STATS_RL512PC	0xA0 | ||||
| #define MT7621_STATS_RL1024PC	0xA4 | ||||
| #define MT7621_STATS_ROC	0xA8 | ||||
| #define MT7621_STATS_RDPC_CTRL	0xB0 | ||||
| #define MT7621_STATS_RDPC_ING	0xB4 | ||||
| #define MT7621_STATS_RDPC_ARL	0xB8 | ||||
|  | ||||
| int mt7530_probe(struct device *dev, void __iomem *base, struct mii_bus *bus, int vlan); | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										1595
									
								
								target/linux/ramips/files-4.9/drivers/net/ethernet/mtk/mtk_eth_soc.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1595
									
								
								target/linux/ramips/files-4.9/drivers/net/ethernet/mtk/mtk_eth_soc.c
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,523 @@ | ||||
| /*   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; version 2 of the License | ||||
|  * | ||||
|  *   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. | ||||
|  * | ||||
|  *   Copyright (C) 2009-2015 John Crispin <blogic@openwrt.org> | ||||
|  *   Copyright (C) 2009-2015 Felix Fietkau <nbd@nbd.name> | ||||
|  *   Copyright (C) 2013-2015 Michael Lee <igvtee@gmail.com> | ||||
|  */ | ||||
|  | ||||
| #ifndef FE_ETH_H | ||||
| #define FE_ETH_H | ||||
|  | ||||
| #include <linux/mii.h> | ||||
| #include <linux/interrupt.h> | ||||
| #include <linux/netdevice.h> | ||||
| #include <linux/dma-mapping.h> | ||||
| #include <linux/phy.h> | ||||
| #include <linux/ethtool.h> | ||||
| #include <linux/version.h> | ||||
|  | ||||
| enum fe_reg { | ||||
| 	FE_REG_PDMA_GLO_CFG = 0, | ||||
| 	FE_REG_PDMA_RST_CFG, | ||||
| 	FE_REG_DLY_INT_CFG, | ||||
| 	FE_REG_TX_BASE_PTR0, | ||||
| 	FE_REG_TX_MAX_CNT0, | ||||
| 	FE_REG_TX_CTX_IDX0, | ||||
| 	FE_REG_TX_DTX_IDX0, | ||||
| 	FE_REG_RX_BASE_PTR0, | ||||
| 	FE_REG_RX_MAX_CNT0, | ||||
| 	FE_REG_RX_CALC_IDX0, | ||||
| 	FE_REG_RX_DRX_IDX0, | ||||
| 	FE_REG_FE_INT_ENABLE, | ||||
| 	FE_REG_FE_INT_STATUS, | ||||
| 	FE_REG_FE_DMA_VID_BASE, | ||||
| 	FE_REG_FE_COUNTER_BASE, | ||||
| 	FE_REG_FE_RST_GL, | ||||
| 	FE_REG_FE_INT_STATUS2, | ||||
| 	FE_REG_COUNT | ||||
| }; | ||||
|  | ||||
| enum fe_work_flag { | ||||
| 	FE_FLAG_RESET_PENDING, | ||||
| 	FE_FLAG_MAX | ||||
| }; | ||||
|  | ||||
| #define MTK_FE_DRV_VERSION		"0.1.2" | ||||
|  | ||||
| /* power of 2 to let NEXT_TX_DESP_IDX work */ | ||||
| #define NUM_DMA_DESC		BIT(7) | ||||
| #define MAX_DMA_DESC		0xfff | ||||
|  | ||||
| #define FE_DELAY_EN_INT		0x80 | ||||
| #define FE_DELAY_MAX_INT	0x04 | ||||
| #define FE_DELAY_MAX_TOUT	0x04 | ||||
| #define FE_DELAY_TIME		20 | ||||
| #define FE_DELAY_CHAN		(((FE_DELAY_EN_INT | FE_DELAY_MAX_INT) << 8) | \ | ||||
| 				 FE_DELAY_MAX_TOUT) | ||||
| #define FE_DELAY_INIT		((FE_DELAY_CHAN << 16) | FE_DELAY_CHAN) | ||||
| #define FE_PSE_FQFC_CFG_INIT	0x80504000 | ||||
| #define FE_PSE_FQFC_CFG_256Q	0xff908000 | ||||
|  | ||||
| /* interrupt bits */ | ||||
| #define FE_CNT_PPE_AF		BIT(31) | ||||
| #define FE_CNT_GDM_AF		BIT(29) | ||||
| #define FE_PSE_P2_FC		BIT(26) | ||||
| #define FE_PSE_BUF_DROP		BIT(24) | ||||
| #define FE_GDM_OTHER_DROP	BIT(23) | ||||
| #define FE_PSE_P1_FC		BIT(22) | ||||
| #define FE_PSE_P0_FC		BIT(21) | ||||
| #define FE_PSE_FQ_EMPTY		BIT(20) | ||||
| #define FE_GE1_STA_CHG		BIT(18) | ||||
| #define FE_TX_COHERENT		BIT(17) | ||||
| #define FE_RX_COHERENT		BIT(16) | ||||
| #define FE_TX_DONE_INT3		BIT(11) | ||||
| #define FE_TX_DONE_INT2		BIT(10) | ||||
| #define FE_TX_DONE_INT1		BIT(9) | ||||
| #define FE_TX_DONE_INT0		BIT(8) | ||||
| #define FE_RX_DONE_INT0		BIT(2) | ||||
| #define FE_TX_DLY_INT		BIT(1) | ||||
| #define FE_RX_DLY_INT		BIT(0) | ||||
|  | ||||
| #define FE_RX_DONE_INT		FE_RX_DONE_INT0 | ||||
| #define FE_TX_DONE_INT		(FE_TX_DONE_INT0 | FE_TX_DONE_INT1 | \ | ||||
| 				 FE_TX_DONE_INT2 | FE_TX_DONE_INT3) | ||||
|  | ||||
| #define RT5350_RX_DLY_INT	BIT(30) | ||||
| #define RT5350_TX_DLY_INT	BIT(28) | ||||
| #define RT5350_RX_DONE_INT1	BIT(17) | ||||
| #define RT5350_RX_DONE_INT0	BIT(16) | ||||
| #define RT5350_TX_DONE_INT3	BIT(3) | ||||
| #define RT5350_TX_DONE_INT2	BIT(2) | ||||
| #define RT5350_TX_DONE_INT1	BIT(1) | ||||
| #define RT5350_TX_DONE_INT0	BIT(0) | ||||
|  | ||||
| #define RT5350_RX_DONE_INT	(RT5350_RX_DONE_INT0 | RT5350_RX_DONE_INT1) | ||||
| #define RT5350_TX_DONE_INT	(RT5350_TX_DONE_INT0 | RT5350_TX_DONE_INT1 | \ | ||||
| 				 RT5350_TX_DONE_INT2 | RT5350_TX_DONE_INT3) | ||||
|  | ||||
| /* registers */ | ||||
| #define FE_FE_OFFSET		0x0000 | ||||
| #define FE_GDMA_OFFSET		0x0020 | ||||
| #define FE_PSE_OFFSET		0x0040 | ||||
| #define FE_GDMA2_OFFSET		0x0060 | ||||
| #define FE_CDMA_OFFSET		0x0080 | ||||
| #define FE_DMA_VID0		0x00a8 | ||||
| #define FE_PDMA_OFFSET		0x0100 | ||||
| #define FE_PPE_OFFSET		0x0200 | ||||
| #define FE_CMTABLE_OFFSET	0x0400 | ||||
| #define FE_POLICYTABLE_OFFSET	0x1000 | ||||
|  | ||||
| #define RT5350_PDMA_OFFSET	0x0800 | ||||
| #define RT5350_SDM_OFFSET	0x0c00 | ||||
|  | ||||
| #define FE_MDIO_ACCESS		(FE_FE_OFFSET + 0x00) | ||||
| #define FE_MDIO_CFG		(FE_FE_OFFSET + 0x04) | ||||
| #define FE_FE_GLO_CFG		(FE_FE_OFFSET + 0x08) | ||||
| #define FE_FE_RST_GL		(FE_FE_OFFSET + 0x0C) | ||||
| #define FE_FE_INT_STATUS	(FE_FE_OFFSET + 0x10) | ||||
| #define FE_FE_INT_ENABLE	(FE_FE_OFFSET + 0x14) | ||||
| #define FE_MDIO_CFG2		(FE_FE_OFFSET + 0x18) | ||||
| #define FE_FOC_TS_T		(FE_FE_OFFSET + 0x1C) | ||||
|  | ||||
| #define	FE_GDMA1_FWD_CFG	(FE_GDMA_OFFSET + 0x00) | ||||
| #define FE_GDMA1_SCH_CFG	(FE_GDMA_OFFSET + 0x04) | ||||
| #define FE_GDMA1_SHPR_CFG	(FE_GDMA_OFFSET + 0x08) | ||||
| #define FE_GDMA1_MAC_ADRL	(FE_GDMA_OFFSET + 0x0C) | ||||
| #define FE_GDMA1_MAC_ADRH	(FE_GDMA_OFFSET + 0x10) | ||||
|  | ||||
| #define	FE_GDMA2_FWD_CFG	(FE_GDMA2_OFFSET + 0x00) | ||||
| #define FE_GDMA2_SCH_CFG	(FE_GDMA2_OFFSET + 0x04) | ||||
| #define FE_GDMA2_SHPR_CFG	(FE_GDMA2_OFFSET + 0x08) | ||||
| #define FE_GDMA2_MAC_ADRL	(FE_GDMA2_OFFSET + 0x0C) | ||||
| #define FE_GDMA2_MAC_ADRH	(FE_GDMA2_OFFSET + 0x10) | ||||
|  | ||||
| #define FE_PSE_FQ_CFG		(FE_PSE_OFFSET + 0x00) | ||||
| #define FE_CDMA_FC_CFG		(FE_PSE_OFFSET + 0x04) | ||||
| #define FE_GDMA1_FC_CFG		(FE_PSE_OFFSET + 0x08) | ||||
| #define FE_GDMA2_FC_CFG		(FE_PSE_OFFSET + 0x0C) | ||||
|  | ||||
| #define FE_CDMA_CSG_CFG		(FE_CDMA_OFFSET + 0x00) | ||||
| #define FE_CDMA_SCH_CFG		(FE_CDMA_OFFSET + 0x04) | ||||
|  | ||||
| #ifdef CONFIG_SOC_MT7621 | ||||
| #define MT7620A_GDMA_OFFSET		0x0500 | ||||
| #else | ||||
| #define MT7620A_GDMA_OFFSET		0x0600 | ||||
| #endif | ||||
| #define	MT7620A_GDMA1_FWD_CFG		(MT7620A_GDMA_OFFSET + 0x00) | ||||
| #define MT7620A_FE_GDMA1_SCH_CFG	(MT7620A_GDMA_OFFSET + 0x04) | ||||
| #define MT7620A_FE_GDMA1_SHPR_CFG	(MT7620A_GDMA_OFFSET + 0x08) | ||||
| #define MT7620A_FE_GDMA1_MAC_ADRL	(MT7620A_GDMA_OFFSET + 0x0C) | ||||
| #define MT7620A_FE_GDMA1_MAC_ADRH	(MT7620A_GDMA_OFFSET + 0x10) | ||||
|  | ||||
| #define RT5350_TX_BASE_PTR0	(RT5350_PDMA_OFFSET + 0x00) | ||||
| #define RT5350_TX_MAX_CNT0	(RT5350_PDMA_OFFSET + 0x04) | ||||
| #define RT5350_TX_CTX_IDX0	(RT5350_PDMA_OFFSET + 0x08) | ||||
| #define RT5350_TX_DTX_IDX0	(RT5350_PDMA_OFFSET + 0x0C) | ||||
| #define RT5350_TX_BASE_PTR1	(RT5350_PDMA_OFFSET + 0x10) | ||||
| #define RT5350_TX_MAX_CNT1	(RT5350_PDMA_OFFSET + 0x14) | ||||
| #define RT5350_TX_CTX_IDX1	(RT5350_PDMA_OFFSET + 0x18) | ||||
| #define RT5350_TX_DTX_IDX1	(RT5350_PDMA_OFFSET + 0x1C) | ||||
| #define RT5350_TX_BASE_PTR2	(RT5350_PDMA_OFFSET + 0x20) | ||||
| #define RT5350_TX_MAX_CNT2	(RT5350_PDMA_OFFSET + 0x24) | ||||
| #define RT5350_TX_CTX_IDX2	(RT5350_PDMA_OFFSET + 0x28) | ||||
| #define RT5350_TX_DTX_IDX2	(RT5350_PDMA_OFFSET + 0x2C) | ||||
| #define RT5350_TX_BASE_PTR3	(RT5350_PDMA_OFFSET + 0x30) | ||||
| #define RT5350_TX_MAX_CNT3	(RT5350_PDMA_OFFSET + 0x34) | ||||
| #define RT5350_TX_CTX_IDX3	(RT5350_PDMA_OFFSET + 0x38) | ||||
| #define RT5350_TX_DTX_IDX3	(RT5350_PDMA_OFFSET + 0x3C) | ||||
| #define RT5350_RX_BASE_PTR0	(RT5350_PDMA_OFFSET + 0x100) | ||||
| #define RT5350_RX_MAX_CNT0	(RT5350_PDMA_OFFSET + 0x104) | ||||
| #define RT5350_RX_CALC_IDX0	(RT5350_PDMA_OFFSET + 0x108) | ||||
| #define RT5350_RX_DRX_IDX0	(RT5350_PDMA_OFFSET + 0x10C) | ||||
| #define RT5350_RX_BASE_PTR1	(RT5350_PDMA_OFFSET + 0x110) | ||||
| #define RT5350_RX_MAX_CNT1	(RT5350_PDMA_OFFSET + 0x114) | ||||
| #define RT5350_RX_CALC_IDX1	(RT5350_PDMA_OFFSET + 0x118) | ||||
| #define RT5350_RX_DRX_IDX1	(RT5350_PDMA_OFFSET + 0x11C) | ||||
| #define RT5350_PDMA_GLO_CFG	(RT5350_PDMA_OFFSET + 0x204) | ||||
| #define RT5350_PDMA_RST_CFG	(RT5350_PDMA_OFFSET + 0x208) | ||||
| #define RT5350_DLY_INT_CFG	(RT5350_PDMA_OFFSET + 0x20c) | ||||
| #define RT5350_FE_INT_STATUS	(RT5350_PDMA_OFFSET + 0x220) | ||||
| #define RT5350_FE_INT_ENABLE	(RT5350_PDMA_OFFSET + 0x228) | ||||
| #define RT5350_PDMA_SCH_CFG	(RT5350_PDMA_OFFSET + 0x280) | ||||
|  | ||||
| #define FE_PDMA_GLO_CFG		(FE_PDMA_OFFSET + 0x00) | ||||
| #define FE_PDMA_RST_CFG		(FE_PDMA_OFFSET + 0x04) | ||||
| #define FE_PDMA_SCH_CFG		(FE_PDMA_OFFSET + 0x08) | ||||
| #define FE_DLY_INT_CFG		(FE_PDMA_OFFSET + 0x0C) | ||||
| #define FE_TX_BASE_PTR0		(FE_PDMA_OFFSET + 0x10) | ||||
| #define FE_TX_MAX_CNT0		(FE_PDMA_OFFSET + 0x14) | ||||
| #define FE_TX_CTX_IDX0		(FE_PDMA_OFFSET + 0x18) | ||||
| #define FE_TX_DTX_IDX0		(FE_PDMA_OFFSET + 0x1C) | ||||
| #define FE_TX_BASE_PTR1		(FE_PDMA_OFFSET + 0x20) | ||||
| #define FE_TX_MAX_CNT1		(FE_PDMA_OFFSET + 0x24) | ||||
| #define FE_TX_CTX_IDX1		(FE_PDMA_OFFSET + 0x28) | ||||
| #define FE_TX_DTX_IDX1		(FE_PDMA_OFFSET + 0x2C) | ||||
| #define FE_RX_BASE_PTR0		(FE_PDMA_OFFSET + 0x30) | ||||
| #define FE_RX_MAX_CNT0		(FE_PDMA_OFFSET + 0x34) | ||||
| #define FE_RX_CALC_IDX0		(FE_PDMA_OFFSET + 0x38) | ||||
| #define FE_RX_DRX_IDX0		(FE_PDMA_OFFSET + 0x3C) | ||||
| #define FE_TX_BASE_PTR2		(FE_PDMA_OFFSET + 0x40) | ||||
| #define FE_TX_MAX_CNT2		(FE_PDMA_OFFSET + 0x44) | ||||
| #define FE_TX_CTX_IDX2		(FE_PDMA_OFFSET + 0x48) | ||||
| #define FE_TX_DTX_IDX2		(FE_PDMA_OFFSET + 0x4C) | ||||
| #define FE_TX_BASE_PTR3		(FE_PDMA_OFFSET + 0x50) | ||||
| #define FE_TX_MAX_CNT3		(FE_PDMA_OFFSET + 0x54) | ||||
| #define FE_TX_CTX_IDX3		(FE_PDMA_OFFSET + 0x58) | ||||
| #define FE_TX_DTX_IDX3		(FE_PDMA_OFFSET + 0x5C) | ||||
| #define FE_RX_BASE_PTR1		(FE_PDMA_OFFSET + 0x60) | ||||
| #define FE_RX_MAX_CNT1		(FE_PDMA_OFFSET + 0x64) | ||||
| #define FE_RX_CALC_IDX1		(FE_PDMA_OFFSET + 0x68) | ||||
| #define FE_RX_DRX_IDX1		(FE_PDMA_OFFSET + 0x6C) | ||||
|  | ||||
| /* Switch DMA configuration */ | ||||
| #define RT5350_SDM_CFG		(RT5350_SDM_OFFSET + 0x00) | ||||
| #define RT5350_SDM_RRING	(RT5350_SDM_OFFSET + 0x04) | ||||
| #define RT5350_SDM_TRING	(RT5350_SDM_OFFSET + 0x08) | ||||
| #define RT5350_SDM_MAC_ADRL	(RT5350_SDM_OFFSET + 0x0C) | ||||
| #define RT5350_SDM_MAC_ADRH	(RT5350_SDM_OFFSET + 0x10) | ||||
| #define RT5350_SDM_TPCNT	(RT5350_SDM_OFFSET + 0x100) | ||||
| #define RT5350_SDM_TBCNT	(RT5350_SDM_OFFSET + 0x104) | ||||
| #define RT5350_SDM_RPCNT	(RT5350_SDM_OFFSET + 0x108) | ||||
| #define RT5350_SDM_RBCNT	(RT5350_SDM_OFFSET + 0x10C) | ||||
| #define RT5350_SDM_CS_ERR	(RT5350_SDM_OFFSET + 0x110) | ||||
|  | ||||
| #define RT5350_SDM_ICS_EN	BIT(16) | ||||
| #define RT5350_SDM_TCS_EN	BIT(17) | ||||
| #define RT5350_SDM_UCS_EN	BIT(18) | ||||
|  | ||||
| /* MDIO_CFG register bits */ | ||||
| #define FE_MDIO_CFG_AUTO_POLL_EN	BIT(29) | ||||
| #define FE_MDIO_CFG_GP1_BP_EN		BIT(16) | ||||
| #define FE_MDIO_CFG_GP1_FRC_EN		BIT(15) | ||||
| #define FE_MDIO_CFG_GP1_SPEED_10	(0 << 13) | ||||
| #define FE_MDIO_CFG_GP1_SPEED_100	(1 << 13) | ||||
| #define FE_MDIO_CFG_GP1_SPEED_1000	(2 << 13) | ||||
| #define FE_MDIO_CFG_GP1_DUPLEX		BIT(12) | ||||
| #define FE_MDIO_CFG_GP1_FC_TX		BIT(11) | ||||
| #define FE_MDIO_CFG_GP1_FC_RX		BIT(10) | ||||
| #define FE_MDIO_CFG_GP1_LNK_DWN		BIT(9) | ||||
| #define FE_MDIO_CFG_GP1_AN_FAIL		BIT(8) | ||||
| #define FE_MDIO_CFG_MDC_CLK_DIV_1	(0 << 6) | ||||
| #define FE_MDIO_CFG_MDC_CLK_DIV_2	(1 << 6) | ||||
| #define FE_MDIO_CFG_MDC_CLK_DIV_4	(2 << 6) | ||||
| #define FE_MDIO_CFG_MDC_CLK_DIV_8	(3 << 6) | ||||
| #define FE_MDIO_CFG_TURBO_MII_FREQ	BIT(5) | ||||
| #define FE_MDIO_CFG_TURBO_MII_MODE	BIT(4) | ||||
| #define FE_MDIO_CFG_RX_CLK_SKEW_0	(0 << 2) | ||||
| #define FE_MDIO_CFG_RX_CLK_SKEW_200	(1 << 2) | ||||
| #define FE_MDIO_CFG_RX_CLK_SKEW_400	(2 << 2) | ||||
| #define FE_MDIO_CFG_RX_CLK_SKEW_INV	(3 << 2) | ||||
| #define FE_MDIO_CFG_TX_CLK_SKEW_0	0 | ||||
| #define FE_MDIO_CFG_TX_CLK_SKEW_200	1 | ||||
| #define FE_MDIO_CFG_TX_CLK_SKEW_400	2 | ||||
| #define FE_MDIO_CFG_TX_CLK_SKEW_INV	3 | ||||
|  | ||||
| /* uni-cast port */ | ||||
| #define FE_GDM1_JMB_LEN_MASK	0xf | ||||
| #define FE_GDM1_JMB_LEN_SHIFT	28 | ||||
| #define FE_GDM1_ICS_EN		BIT(22) | ||||
| #define FE_GDM1_TCS_EN		BIT(21) | ||||
| #define FE_GDM1_UCS_EN		BIT(20) | ||||
| #define FE_GDM1_JMB_EN		BIT(19) | ||||
| #define FE_GDM1_STRPCRC		BIT(16) | ||||
| #define FE_GDM1_UFRC_P_CPU	(0 << 12) | ||||
| #define FE_GDM1_UFRC_P_GDMA1	(1 << 12) | ||||
| #define FE_GDM1_UFRC_P_PPE	(6 << 12) | ||||
|  | ||||
| /* checksums */ | ||||
| #define FE_ICS_GEN_EN		BIT(2) | ||||
| #define FE_UCS_GEN_EN		BIT(1) | ||||
| #define FE_TCS_GEN_EN		BIT(0) | ||||
|  | ||||
| /* dma ring */ | ||||
| #define FE_PST_DRX_IDX0		BIT(16) | ||||
| #define FE_PST_DTX_IDX3		BIT(3) | ||||
| #define FE_PST_DTX_IDX2		BIT(2) | ||||
| #define FE_PST_DTX_IDX1		BIT(1) | ||||
| #define FE_PST_DTX_IDX0		BIT(0) | ||||
|  | ||||
| #define FE_RX_2B_OFFSET		BIT(31) | ||||
| #define FE_TX_WB_DDONE		BIT(6) | ||||
| #define FE_RX_DMA_BUSY		BIT(3) | ||||
| #define FE_TX_DMA_BUSY		BIT(1) | ||||
| #define FE_RX_DMA_EN		BIT(2) | ||||
| #define FE_TX_DMA_EN		BIT(0) | ||||
|  | ||||
| #define FE_PDMA_SIZE_4DWORDS	(0 << 4) | ||||
| #define FE_PDMA_SIZE_8DWORDS	(1 << 4) | ||||
| #define FE_PDMA_SIZE_16DWORDS	(2 << 4) | ||||
|  | ||||
| #define FE_US_CYC_CNT_MASK	0xff | ||||
| #define FE_US_CYC_CNT_SHIFT	0x8 | ||||
| #define FE_US_CYC_CNT_DIVISOR	1000000 | ||||
|  | ||||
| /* rxd2 */ | ||||
| #define RX_DMA_DONE		BIT(31) | ||||
| #define RX_DMA_LSO		BIT(30) | ||||
| #define RX_DMA_PLEN0(_x)	(((_x) & 0x3fff) << 16) | ||||
| #define RX_DMA_GET_PLEN0(_x)	(((_x) >> 16) & 0x3fff) | ||||
| #define RX_DMA_TAG		BIT(15) | ||||
| /* rxd3 */ | ||||
| #define RX_DMA_TPID(_x)		(((_x) >> 16) & 0xffff) | ||||
| #define RX_DMA_VID(_x)		((_x) & 0xffff) | ||||
| /* rxd4 */ | ||||
| #define RX_DMA_L4VALID		BIT(30) | ||||
|  | ||||
| struct fe_rx_dma { | ||||
| 	unsigned int rxd1; | ||||
| 	unsigned int rxd2; | ||||
| 	unsigned int rxd3; | ||||
| 	unsigned int rxd4; | ||||
| } __packed __aligned(4); | ||||
|  | ||||
| #define TX_DMA_BUF_LEN		0x3fff | ||||
| #define TX_DMA_PLEN0_MASK	(TX_DMA_BUF_LEN << 16) | ||||
| #define TX_DMA_PLEN0(_x)	(((_x) & TX_DMA_BUF_LEN) << 16) | ||||
| #define TX_DMA_PLEN1(_x)	((_x) & TX_DMA_BUF_LEN) | ||||
| #define TX_DMA_GET_PLEN0(_x)    (((_x) >> 16) & TX_DMA_BUF_LEN) | ||||
| #define TX_DMA_GET_PLEN1(_x)    ((_x) & TX_DMA_BUF_LEN) | ||||
| #define TX_DMA_LS1		BIT(14) | ||||
| #define TX_DMA_LS0		BIT(30) | ||||
| #define TX_DMA_DONE		BIT(31) | ||||
|  | ||||
| #define TX_DMA_INS_VLAN_MT7621	BIT(16) | ||||
| #define TX_DMA_INS_VLAN		BIT(7) | ||||
| #define TX_DMA_INS_PPPOE	BIT(12) | ||||
| #define TX_DMA_QN(_x)		((_x) << 16) | ||||
| #define TX_DMA_PN(_x)		((_x) << 24) | ||||
| #define TX_DMA_QN_MASK		TX_DMA_QN(0x7) | ||||
| #define TX_DMA_PN_MASK		TX_DMA_PN(0x7) | ||||
| #define TX_DMA_UDF		BIT(20) | ||||
| #define TX_DMA_CHKSUM		(0x7 << 29) | ||||
| #define TX_DMA_TSO		BIT(28) | ||||
|  | ||||
| /* frame engine counters */ | ||||
| #define FE_PPE_AC_BCNT0		(FE_CMTABLE_OFFSET + 0x00) | ||||
| #define FE_GDMA1_TX_GBCNT	(FE_CMTABLE_OFFSET + 0x300) | ||||
| #define FE_GDMA2_TX_GBCNT	(FE_GDMA1_TX_GBCNT + 0x40) | ||||
|  | ||||
| /* phy device flags */ | ||||
| #define FE_PHY_FLAG_PORT	BIT(0) | ||||
| #define FE_PHY_FLAG_ATTACH	BIT(1) | ||||
|  | ||||
| struct fe_tx_dma { | ||||
| 	unsigned int txd1; | ||||
| 	unsigned int txd2; | ||||
| 	unsigned int txd3; | ||||
| 	unsigned int txd4; | ||||
| } __packed __aligned(4); | ||||
|  | ||||
| struct fe_priv; | ||||
|  | ||||
| struct fe_phy { | ||||
| 	/* make sure that phy operations are atomic */ | ||||
| 	spinlock_t		lock; | ||||
|  | ||||
| 	struct phy_device	*phy[8]; | ||||
| 	struct device_node	*phy_node[8]; | ||||
| 	const __be32		*phy_fixed[8]; | ||||
| 	int			duplex[8]; | ||||
| 	int			speed[8]; | ||||
| 	int			tx_fc[8]; | ||||
| 	int			rx_fc[8]; | ||||
| 	int (*connect)(struct fe_priv *priv); | ||||
| 	void (*disconnect)(struct fe_priv *priv); | ||||
| 	void (*start)(struct fe_priv *priv); | ||||
| 	void (*stop)(struct fe_priv *priv); | ||||
| }; | ||||
|  | ||||
| struct fe_soc_data { | ||||
| 	const u16 *reg_table; | ||||
|  | ||||
| 	void (*init_data)(struct fe_soc_data *data, struct net_device *netdev); | ||||
| 	void (*reset_fe)(void); | ||||
| 	void (*set_mac)(struct fe_priv *priv, unsigned char *mac); | ||||
| 	int (*fwd_config)(struct fe_priv *priv); | ||||
| 	void (*tx_dma)(struct fe_tx_dma *txd); | ||||
| 	int (*switch_init)(struct fe_priv *priv); | ||||
| 	int (*switch_config)(struct fe_priv *priv); | ||||
| 	void (*port_init)(struct fe_priv *priv, struct device_node *port); | ||||
| 	int (*has_carrier)(struct fe_priv *priv); | ||||
| 	int (*mdio_init)(struct fe_priv *priv); | ||||
| 	void (*mdio_cleanup)(struct fe_priv *priv); | ||||
| 	int (*mdio_write)(struct mii_bus *bus, int phy_addr, int phy_reg, | ||||
| 			  u16 val); | ||||
| 	int (*mdio_read)(struct mii_bus *bus, int phy_addr, int phy_reg); | ||||
| 	void (*mdio_adjust_link)(struct fe_priv *priv, int port); | ||||
|  | ||||
| 	void *swpriv; | ||||
| 	u32 pdma_glo_cfg; | ||||
| 	u32 rx_int; | ||||
| 	u32 tx_int; | ||||
| 	u32 status_int; | ||||
| 	u32 checksum_bit; | ||||
| }; | ||||
|  | ||||
| #define FE_FLAG_PADDING_64B		BIT(0) | ||||
| #define FE_FLAG_PADDING_BUG		BIT(1) | ||||
| #define FE_FLAG_JUMBO_FRAME		BIT(2) | ||||
| #define FE_FLAG_RX_2B_OFFSET		BIT(3) | ||||
| #define FE_FLAG_RX_SG_DMA		BIT(4) | ||||
| #define FE_FLAG_RX_VLAN_CTAG		BIT(5) | ||||
| #define FE_FLAG_NAPI_WEIGHT		BIT(6) | ||||
| #define FE_FLAG_CALIBRATE_CLK		BIT(7) | ||||
| #define FE_FLAG_HAS_SWITCH		BIT(8) | ||||
|  | ||||
| #define FE_STAT_REG_DECLARE		\ | ||||
| 	_FE(tx_bytes)			\ | ||||
| 	_FE(tx_packets)			\ | ||||
| 	_FE(tx_skip)			\ | ||||
| 	_FE(tx_collisions)		\ | ||||
| 	_FE(rx_bytes)			\ | ||||
| 	_FE(rx_packets)			\ | ||||
| 	_FE(rx_overflow)		\ | ||||
| 	_FE(rx_fcs_errors)		\ | ||||
| 	_FE(rx_short_errors)		\ | ||||
| 	_FE(rx_long_errors)		\ | ||||
| 	_FE(rx_checksum_errors)		\ | ||||
| 	_FE(rx_flow_control_packets) | ||||
|  | ||||
| struct fe_hw_stats { | ||||
| 	/* make sure that stats operations are atomic */ | ||||
| 	spinlock_t stats_lock; | ||||
|  | ||||
| 	struct u64_stats_sync syncp; | ||||
| #define _FE(x) u64 x; | ||||
| 	FE_STAT_REG_DECLARE | ||||
| #undef _FE | ||||
| }; | ||||
|  | ||||
| enum fe_tx_flags { | ||||
| 	FE_TX_FLAGS_SINGLE0	= 0x01, | ||||
| 	FE_TX_FLAGS_PAGE0	= 0x02, | ||||
| 	FE_TX_FLAGS_PAGE1	= 0x04, | ||||
| }; | ||||
|  | ||||
| struct fe_tx_buf { | ||||
| 	struct sk_buff *skb; | ||||
| 	u32 flags; | ||||
| 	DEFINE_DMA_UNMAP_ADDR(dma_addr0); | ||||
| 	DEFINE_DMA_UNMAP_LEN(dma_len0); | ||||
| 	DEFINE_DMA_UNMAP_ADDR(dma_addr1); | ||||
| 	DEFINE_DMA_UNMAP_LEN(dma_len1); | ||||
| }; | ||||
|  | ||||
| struct fe_tx_ring { | ||||
| 	struct fe_tx_dma *tx_dma; | ||||
| 	struct fe_tx_buf *tx_buf; | ||||
| 	dma_addr_t tx_phys; | ||||
| 	u16 tx_ring_size; | ||||
| 	u16 tx_free_idx; | ||||
| 	u16 tx_next_idx; | ||||
| 	u16 tx_thresh; | ||||
| }; | ||||
|  | ||||
| struct fe_rx_ring { | ||||
| 	struct fe_rx_dma *rx_dma; | ||||
| 	u8 **rx_data; | ||||
| 	dma_addr_t rx_phys; | ||||
| 	u16 rx_ring_size; | ||||
| 	u16 frag_size; | ||||
| 	u16 rx_buf_size; | ||||
| 	u16 rx_calc_idx; | ||||
| }; | ||||
|  | ||||
| struct fe_priv { | ||||
| 	/* make sure that register operations are atomic */ | ||||
| 	spinlock_t			page_lock; | ||||
|  | ||||
| 	struct fe_soc_data		*soc; | ||||
| 	struct net_device		*netdev; | ||||
| 	struct device_node		*switch_np; | ||||
| 	u32				msg_enable; | ||||
| 	u32				flags; | ||||
|  | ||||
| 	struct device			*device; | ||||
| 	unsigned long			sysclk; | ||||
|  | ||||
| 	struct fe_rx_ring		rx_ring; | ||||
| 	struct napi_struct		rx_napi; | ||||
|  | ||||
| 	struct fe_tx_ring               tx_ring; | ||||
|  | ||||
| 	struct fe_phy			*phy; | ||||
| 	struct mii_bus			*mii_bus; | ||||
| 	struct phy_device		*phy_dev; | ||||
| 	u32				phy_flags; | ||||
|  | ||||
| 	int				link[8]; | ||||
|  | ||||
| 	struct fe_hw_stats		*hw_stats; | ||||
| 	unsigned long			vlan_map; | ||||
| 	struct work_struct		pending_work; | ||||
| 	DECLARE_BITMAP(pending_flags, FE_FLAG_MAX); | ||||
| }; | ||||
|  | ||||
| extern const struct of_device_id of_fe_match[]; | ||||
|  | ||||
| void fe_w32(u32 val, unsigned reg); | ||||
| u32 fe_r32(unsigned reg); | ||||
|  | ||||
| int fe_set_clock_cycle(struct fe_priv *priv); | ||||
| void fe_csum_config(struct fe_priv *priv); | ||||
| void fe_stats_update(struct fe_priv *priv); | ||||
| void fe_fwd_config(struct fe_priv *priv); | ||||
| void fe_reg_w32(u32 val, enum fe_reg reg); | ||||
| u32 fe_reg_r32(enum fe_reg reg); | ||||
|  | ||||
| void fe_reset(u32 reset_bits); | ||||
|  | ||||
| static inline void *priv_netdev(struct fe_priv *priv) | ||||
| { | ||||
| 	return (char *)priv - ALIGN(sizeof(struct net_device), NETDEV_ALIGN); | ||||
| } | ||||
|  | ||||
| #endif /* FE_ETH_H */ | ||||
| @@ -0,0 +1,335 @@ | ||||
| /*   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; version 2 of the License | ||||
|  * | ||||
|  *   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. | ||||
|  * | ||||
|  *   Copyright (C) 2009-2015 John Crispin <blogic@openwrt.org> | ||||
|  *   Copyright (C) 2009-2015 Felix Fietkau <nbd@nbd.name> | ||||
|  *   Copyright (C) 2013-2015 Michael Lee <igvtee@gmail.com> | ||||
|  */ | ||||
|  | ||||
| #include <linux/module.h> | ||||
| #include <linux/platform_device.h> | ||||
| #include <linux/if_vlan.h> | ||||
| #include <linux/of_net.h> | ||||
|  | ||||
| #include <asm/mach-ralink/ralink_regs.h> | ||||
|  | ||||
| #include <mt7620.h> | ||||
| #include "mtk_eth_soc.h" | ||||
| #include "gsw_mt7620.h" | ||||
| #include "mt7530.h" | ||||
| #include "mdio.h" | ||||
|  | ||||
| #define MT7620A_CDMA_CSG_CFG	0x400 | ||||
| #define MT7620_DMA_VID		(MT7620A_CDMA_CSG_CFG | 0x30) | ||||
| #define MT7621_CDMP_IG_CTRL	(MT7620A_CDMA_CSG_CFG + 0x00) | ||||
| #define MT7621_CDMP_EG_CTRL	(MT7620A_CDMA_CSG_CFG + 0x04) | ||||
| #define MT7620A_RESET_FE	BIT(21) | ||||
| #define MT7621_RESET_FE		BIT(6) | ||||
| #define MT7620A_RESET_ESW	BIT(23) | ||||
| #define MT7620_L4_VALID		BIT(23) | ||||
| #define MT7621_L4_VALID		BIT(24) | ||||
|  | ||||
| #define MT7620_TX_DMA_UDF	BIT(15) | ||||
| #define MT7621_TX_DMA_UDF	BIT(19) | ||||
| #define TX_DMA_FP_BMAP		((0xff) << 19) | ||||
|  | ||||
| #define CDMA_ICS_EN		BIT(2) | ||||
| #define CDMA_UCS_EN		BIT(1) | ||||
| #define CDMA_TCS_EN		BIT(0) | ||||
|  | ||||
| #define GDMA_ICS_EN		BIT(22) | ||||
| #define GDMA_TCS_EN		BIT(21) | ||||
| #define GDMA_UCS_EN		BIT(20) | ||||
|  | ||||
| /* frame engine counters */ | ||||
| #define MT7620_REG_MIB_OFFSET	0x1000 | ||||
| #define MT7620_PPE_AC_BCNT0	(MT7620_REG_MIB_OFFSET + 0x00) | ||||
| #define MT7620_GDM1_TX_GBCNT	(MT7620_REG_MIB_OFFSET + 0x300) | ||||
| #define MT7620_GDM2_TX_GBCNT	(MT7620_GDM1_TX_GBCNT + 0x40) | ||||
|  | ||||
| #define MT7621_REG_MIB_OFFSET	0x2000 | ||||
| #define MT7621_PPE_AC_BCNT0	(MT7621_REG_MIB_OFFSET + 0x00) | ||||
| #define MT7621_GDM1_TX_GBCNT	(MT7621_REG_MIB_OFFSET + 0x400) | ||||
| #define MT7621_GDM2_TX_GBCNT	(MT7621_GDM1_TX_GBCNT + 0x40) | ||||
|  | ||||
| #define GSW_REG_GDMA1_MAC_ADRL	0x508 | ||||
| #define GSW_REG_GDMA1_MAC_ADRH	0x50C | ||||
|  | ||||
| #define MT7621_FE_RST_GL	(FE_FE_OFFSET + 0x04) | ||||
| #define MT7620_FE_INT_STATUS2	(FE_FE_OFFSET + 0x08) | ||||
|  | ||||
| /* FE_INT_STATUS reg on mt7620 define CNT_GDM1_AF at BIT(29) | ||||
|  * but after test it should be BIT(13). | ||||
|  */ | ||||
| #define MT7620_FE_GDM1_AF	BIT(13) | ||||
| #define MT7621_FE_GDM1_AF	BIT(28) | ||||
| #define MT7621_FE_GDM2_AF	BIT(29) | ||||
|  | ||||
| static const u16 mt7620_reg_table[FE_REG_COUNT] = { | ||||
| 	[FE_REG_PDMA_GLO_CFG] = RT5350_PDMA_GLO_CFG, | ||||
| 	[FE_REG_PDMA_RST_CFG] = RT5350_PDMA_RST_CFG, | ||||
| 	[FE_REG_DLY_INT_CFG] = RT5350_DLY_INT_CFG, | ||||
| 	[FE_REG_TX_BASE_PTR0] = RT5350_TX_BASE_PTR0, | ||||
| 	[FE_REG_TX_MAX_CNT0] = RT5350_TX_MAX_CNT0, | ||||
| 	[FE_REG_TX_CTX_IDX0] = RT5350_TX_CTX_IDX0, | ||||
| 	[FE_REG_TX_DTX_IDX0] = RT5350_TX_DTX_IDX0, | ||||
| 	[FE_REG_RX_BASE_PTR0] = RT5350_RX_BASE_PTR0, | ||||
| 	[FE_REG_RX_MAX_CNT0] = RT5350_RX_MAX_CNT0, | ||||
| 	[FE_REG_RX_CALC_IDX0] = RT5350_RX_CALC_IDX0, | ||||
| 	[FE_REG_RX_DRX_IDX0] = RT5350_RX_DRX_IDX0, | ||||
| 	[FE_REG_FE_INT_ENABLE] = RT5350_FE_INT_ENABLE, | ||||
| 	[FE_REG_FE_INT_STATUS] = RT5350_FE_INT_STATUS, | ||||
| 	[FE_REG_FE_DMA_VID_BASE] = MT7620_DMA_VID, | ||||
| 	[FE_REG_FE_COUNTER_BASE] = MT7620_GDM1_TX_GBCNT, | ||||
| 	[FE_REG_FE_RST_GL] = MT7621_FE_RST_GL, | ||||
| 	[FE_REG_FE_INT_STATUS2] = MT7620_FE_INT_STATUS2, | ||||
| }; | ||||
|  | ||||
| static int mt7620_gsw_config(struct fe_priv *priv) | ||||
| { | ||||
| 	struct mt7620_gsw *gsw = (struct mt7620_gsw *) priv->soc->swpriv; | ||||
|  | ||||
| 	/* is the mt7530 internal or external */ | ||||
| 	if (priv->mii_bus && mdiobus_get_phy(priv->mii_bus, 0x1f)) { | ||||
| 		mt7530_probe(priv->device, gsw->base, NULL, 0); | ||||
| 		mt7530_probe(priv->device, NULL, priv->mii_bus, 1); | ||||
| 	} else { | ||||
| 		mt7530_probe(priv->device, gsw->base, NULL, 1); | ||||
| 	} | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static void mt7620_set_mac(struct fe_priv *priv, unsigned char *mac) | ||||
| { | ||||
| 	struct mt7620_gsw *gsw = (struct mt7620_gsw *)priv->soc->swpriv; | ||||
| 	unsigned long flags; | ||||
|  | ||||
| 	spin_lock_irqsave(&priv->page_lock, flags); | ||||
| 	mtk_switch_w32(gsw, (mac[0] << 8) | mac[1], GSW_REG_SMACCR1); | ||||
| 	mtk_switch_w32(gsw, (mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5], | ||||
| 		GSW_REG_SMACCR0); | ||||
| 	spin_unlock_irqrestore(&priv->page_lock, flags); | ||||
| } | ||||
|  | ||||
| static void mt7620_auto_poll(struct mt7620_gsw *gsw) | ||||
| { | ||||
| 	int phy; | ||||
| 	int lsb = -1, msb = 0; | ||||
|  | ||||
| 	for_each_set_bit(phy, &gsw->autopoll, 32) { | ||||
| 		if (lsb < 0) | ||||
| 			lsb = phy; | ||||
| 		msb = phy; | ||||
| 	} | ||||
|  | ||||
| 	if (lsb == msb) | ||||
| 		lsb--; | ||||
|  | ||||
| 	mtk_switch_w32(gsw, PHY_AN_EN | PHY_PRE_EN | PMY_MDC_CONF(5) | | ||||
| 		(msb << 8) | lsb, ESW_PHY_POLLING); | ||||
| } | ||||
|  | ||||
| static void mt7620_port_init(struct fe_priv *priv, struct device_node *np) | ||||
| { | ||||
| 	struct mt7620_gsw *gsw = (struct mt7620_gsw *)priv->soc->swpriv; | ||||
| 	const __be32 *_id = of_get_property(np, "reg", NULL); | ||||
| 	int phy_mode, size, id; | ||||
| 	int shift = 12; | ||||
| 	u32 val, mask = 0; | ||||
| 	int min = (gsw->port4 == PORT4_EPHY) ? (5) : (4); | ||||
|  | ||||
| 	if (!_id || (be32_to_cpu(*_id) < min) || (be32_to_cpu(*_id) > 5)) { | ||||
| 		if (_id) | ||||
| 			pr_err("%s: invalid port id %d\n", np->name, | ||||
| 			       be32_to_cpu(*_id)); | ||||
| 		else | ||||
| 			pr_err("%s: invalid port id\n", np->name); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	id = be32_to_cpu(*_id); | ||||
|  | ||||
| 	if (id == 4) | ||||
| 		shift = 14; | ||||
|  | ||||
| 	priv->phy->phy_fixed[id] = of_get_property(np, "mediatek,fixed-link", | ||||
| 						   &size); | ||||
| 	if (priv->phy->phy_fixed[id] && | ||||
| 	    (size != (4 * sizeof(*priv->phy->phy_fixed[id])))) { | ||||
| 		pr_err("%s: invalid fixed link property\n", np->name); | ||||
| 		priv->phy->phy_fixed[id] = NULL; | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	phy_mode = of_get_phy_mode(np); | ||||
| 	switch (phy_mode) { | ||||
| 	case PHY_INTERFACE_MODE_RGMII: | ||||
| 		mask = 0; | ||||
| 		break; | ||||
| 	case PHY_INTERFACE_MODE_MII: | ||||
| 		mask = 1; | ||||
| 		break; | ||||
| 	case PHY_INTERFACE_MODE_RMII: | ||||
| 		mask = 2; | ||||
| 		break; | ||||
| 	default: | ||||
| 		dev_err(priv->device, "port %d - invalid phy mode\n", id); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	priv->phy->phy_node[id] = of_parse_phandle(np, "phy-handle", 0); | ||||
| 	if (!priv->phy->phy_node[id] && !priv->phy->phy_fixed[id]) | ||||
| 		return; | ||||
|  | ||||
| 	val = rt_sysc_r32(SYSC_REG_CFG1); | ||||
| 	val &= ~(3 << shift); | ||||
| 	val |= mask << shift; | ||||
| 	rt_sysc_w32(val, SYSC_REG_CFG1); | ||||
|  | ||||
| 	if (priv->phy->phy_fixed[id]) { | ||||
| 		const __be32 *link = priv->phy->phy_fixed[id]; | ||||
| 		int tx_fc, rx_fc; | ||||
| 		u32 val = 0; | ||||
|  | ||||
| 		priv->phy->speed[id] = be32_to_cpup(link++); | ||||
| 		tx_fc = be32_to_cpup(link++); | ||||
| 		rx_fc = be32_to_cpup(link++); | ||||
| 		priv->phy->duplex[id] = be32_to_cpup(link++); | ||||
| 		priv->link[id] = 1; | ||||
|  | ||||
| 		switch (priv->phy->speed[id]) { | ||||
| 		case SPEED_10: | ||||
| 			val = 0; | ||||
| 			break; | ||||
| 		case SPEED_100: | ||||
| 			val = 1; | ||||
| 			break; | ||||
| 		case SPEED_1000: | ||||
| 			val = 2; | ||||
| 			break; | ||||
| 		default: | ||||
| 			dev_err(priv->device, "invalid link speed: %d\n", | ||||
| 				priv->phy->speed[id]); | ||||
| 			priv->phy->phy_fixed[id] = 0; | ||||
| 			return; | ||||
| 		} | ||||
| 		val = PMCR_SPEED(val); | ||||
| 		val |= PMCR_LINK | PMCR_BACKPRES | PMCR_BACKOFF | PMCR_RX_EN | | ||||
| 			PMCR_TX_EN | PMCR_FORCE | PMCR_MAC_MODE | PMCR_IPG; | ||||
| 		if (tx_fc) | ||||
| 			val |= PMCR_TX_FC; | ||||
| 		if (rx_fc) | ||||
| 			val |= PMCR_RX_FC; | ||||
| 		if (priv->phy->duplex[id]) | ||||
| 			val |= PMCR_DUPLEX; | ||||
| 		mtk_switch_w32(gsw, val, GSW_REG_PORT_PMCR(id)); | ||||
| 		dev_info(priv->device, "using fixed link parameters\n"); | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	if (priv->phy->phy_node[id] && mdiobus_get_phy(priv->mii_bus, id)) { | ||||
| 		u32 val = PMCR_BACKPRES | PMCR_BACKOFF | PMCR_RX_EN | | ||||
| 			PMCR_TX_EN |  PMCR_MAC_MODE | PMCR_IPG; | ||||
|  | ||||
| 		mtk_switch_w32(gsw, val, GSW_REG_PORT_PMCR(id)); | ||||
| 		fe_connect_phy_node(priv, priv->phy->phy_node[id]); | ||||
| 		gsw->autopoll |= BIT(id); | ||||
| 		mt7620_auto_poll(gsw); | ||||
| 		return; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static void mt7620_fe_reset(void) | ||||
| { | ||||
| 	fe_reset(MT7620A_RESET_FE | MT7620A_RESET_ESW); | ||||
| } | ||||
|  | ||||
| static void mt7620_rxcsum_config(bool enable) | ||||
| { | ||||
| 	if (enable) | ||||
| 		fe_w32(fe_r32(MT7620A_GDMA1_FWD_CFG) | (GDMA_ICS_EN | | ||||
| 					GDMA_TCS_EN | GDMA_UCS_EN), | ||||
| 				MT7620A_GDMA1_FWD_CFG); | ||||
| 	else | ||||
| 		fe_w32(fe_r32(MT7620A_GDMA1_FWD_CFG) & ~(GDMA_ICS_EN | | ||||
| 					GDMA_TCS_EN | GDMA_UCS_EN), | ||||
| 				MT7620A_GDMA1_FWD_CFG); | ||||
| } | ||||
|  | ||||
| static void mt7620_txcsum_config(bool enable) | ||||
| { | ||||
| 	if (enable) | ||||
| 		fe_w32(fe_r32(MT7620A_CDMA_CSG_CFG) | (CDMA_ICS_EN | | ||||
| 					CDMA_UCS_EN | CDMA_TCS_EN), | ||||
| 				MT7620A_CDMA_CSG_CFG); | ||||
| 	else | ||||
| 		fe_w32(fe_r32(MT7620A_CDMA_CSG_CFG) & ~(CDMA_ICS_EN | | ||||
| 					CDMA_UCS_EN | CDMA_TCS_EN), | ||||
| 				MT7620A_CDMA_CSG_CFG); | ||||
| } | ||||
|  | ||||
| static int mt7620_fwd_config(struct fe_priv *priv) | ||||
| { | ||||
| 	struct net_device *dev = priv_netdev(priv); | ||||
|  | ||||
| 	fe_w32(fe_r32(MT7620A_GDMA1_FWD_CFG) & ~7, MT7620A_GDMA1_FWD_CFG); | ||||
|  | ||||
| 	mt7620_txcsum_config((dev->features & NETIF_F_IP_CSUM)); | ||||
| 	mt7620_rxcsum_config((dev->features & NETIF_F_RXCSUM)); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static void mt7620_tx_dma(struct fe_tx_dma *txd) | ||||
| { | ||||
| } | ||||
|  | ||||
| static void mt7620_init_data(struct fe_soc_data *data, | ||||
| 			     struct net_device *netdev) | ||||
| { | ||||
| 	struct fe_priv *priv = netdev_priv(netdev); | ||||
|  | ||||
| 	priv->flags = FE_FLAG_PADDING_64B | FE_FLAG_RX_2B_OFFSET | | ||||
| 		FE_FLAG_RX_SG_DMA | FE_FLAG_HAS_SWITCH; | ||||
|  | ||||
| 	netdev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | | ||||
| 		NETIF_F_HW_VLAN_CTAG_TX; | ||||
| 	if (mt7620_get_eco() >= 5) | ||||
| 		netdev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | | ||||
| 			NETIF_F_IPV6_CSUM; | ||||
| } | ||||
|  | ||||
| static struct fe_soc_data mt7620_data = { | ||||
| 	.init_data = mt7620_init_data, | ||||
| 	.reset_fe = mt7620_fe_reset, | ||||
| 	.set_mac = mt7620_set_mac, | ||||
| 	.fwd_config = mt7620_fwd_config, | ||||
| 	.tx_dma = mt7620_tx_dma, | ||||
| 	.switch_init = mtk_gsw_init, | ||||
| 	.switch_config = mt7620_gsw_config, | ||||
| 	.port_init = mt7620_port_init, | ||||
| 	.reg_table = mt7620_reg_table, | ||||
| 	.pdma_glo_cfg = FE_PDMA_SIZE_16DWORDS, | ||||
| 	.rx_int = RT5350_RX_DONE_INT, | ||||
| 	.tx_int = RT5350_TX_DONE_INT, | ||||
| 	.status_int = MT7620_FE_GDM1_AF, | ||||
| 	.checksum_bit = MT7620_L4_VALID, | ||||
| 	.has_carrier = mt7620_has_carrier, | ||||
| 	.mdio_read = mt7620_mdio_read, | ||||
| 	.mdio_write = mt7620_mdio_write, | ||||
| 	.mdio_adjust_link = mt7620_mdio_link_adjust, | ||||
| }; | ||||
|  | ||||
| const struct of_device_id of_fe_match[] = { | ||||
| 	{ .compatible = "mediatek,mt7620-eth", .data = &mt7620_data }, | ||||
| 	{}, | ||||
| }; | ||||
|  | ||||
| MODULE_DEVICE_TABLE(of, of_fe_match); | ||||
| @@ -0,0 +1,185 @@ | ||||
| /*   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; version 2 of the License | ||||
|  * | ||||
|  *   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. | ||||
|  * | ||||
|  *   Copyright (C) 2009-2015 John Crispin <blogic@openwrt.org> | ||||
|  *   Copyright (C) 2009-2015 Felix Fietkau <nbd@nbd.name> | ||||
|  *   Copyright (C) 2013-2015 Michael Lee <igvtee@gmail.com> | ||||
|  */ | ||||
|  | ||||
| #include <linux/module.h> | ||||
| #include <linux/platform_device.h> | ||||
| #include <linux/if_vlan.h> | ||||
| #include <linux/of_net.h> | ||||
|  | ||||
| #include <asm/mach-ralink/ralink_regs.h> | ||||
|  | ||||
| #include "mtk_eth_soc.h" | ||||
| #include "gsw_mt7620.h" | ||||
| #include "mt7530.h" | ||||
| #include "mdio.h" | ||||
|  | ||||
| #define MT7620A_CDMA_CSG_CFG	0x400 | ||||
| #define MT7621_CDMP_IG_CTRL	(MT7620A_CDMA_CSG_CFG + 0x00) | ||||
| #define MT7621_CDMP_EG_CTRL	(MT7620A_CDMA_CSG_CFG + 0x04) | ||||
| #define MT7621_RESET_FE		BIT(6) | ||||
| #define MT7621_L4_VALID		BIT(24) | ||||
|  | ||||
| #define MT7621_TX_DMA_UDF	BIT(19) | ||||
| #define MT7621_TX_DMA_FPORT	BIT(25) | ||||
|  | ||||
| #define CDMA_ICS_EN		BIT(2) | ||||
| #define CDMA_UCS_EN		BIT(1) | ||||
| #define CDMA_TCS_EN		BIT(0) | ||||
|  | ||||
| #define GDMA_ICS_EN		BIT(22) | ||||
| #define GDMA_TCS_EN		BIT(21) | ||||
| #define GDMA_UCS_EN		BIT(20) | ||||
|  | ||||
| /* frame engine counters */ | ||||
| #define MT7621_REG_MIB_OFFSET	0x2000 | ||||
| #define MT7621_PPE_AC_BCNT0	(MT7621_REG_MIB_OFFSET + 0x00) | ||||
| #define MT7621_GDM1_TX_GBCNT	(MT7621_REG_MIB_OFFSET + 0x400) | ||||
| #define MT7621_GDM2_TX_GBCNT	(MT7621_GDM1_TX_GBCNT + 0x40) | ||||
|  | ||||
| #define GSW_REG_GDMA1_MAC_ADRL	0x508 | ||||
| #define GSW_REG_GDMA1_MAC_ADRH	0x50C | ||||
|  | ||||
| #define MT7621_FE_RST_GL	(FE_FE_OFFSET + 0x04) | ||||
| #define MT7620_FE_INT_STATUS2	(FE_FE_OFFSET + 0x08) | ||||
|  | ||||
| /* FE_INT_STATUS reg on mt7620 define CNT_GDM1_AF at BIT(29) | ||||
|  * but after test it should be BIT(13). | ||||
|  */ | ||||
| #define MT7620_FE_GDM1_AF	BIT(13) | ||||
| #define MT7621_FE_GDM1_AF	BIT(28) | ||||
| #define MT7621_FE_GDM2_AF	BIT(29) | ||||
|  | ||||
| static const u16 mt7621_reg_table[FE_REG_COUNT] = { | ||||
| 	[FE_REG_PDMA_GLO_CFG] = RT5350_PDMA_GLO_CFG, | ||||
| 	[FE_REG_PDMA_RST_CFG] = RT5350_PDMA_RST_CFG, | ||||
| 	[FE_REG_DLY_INT_CFG] = RT5350_DLY_INT_CFG, | ||||
| 	[FE_REG_TX_BASE_PTR0] = RT5350_TX_BASE_PTR0, | ||||
| 	[FE_REG_TX_MAX_CNT0] = RT5350_TX_MAX_CNT0, | ||||
| 	[FE_REG_TX_CTX_IDX0] = RT5350_TX_CTX_IDX0, | ||||
| 	[FE_REG_TX_DTX_IDX0] = RT5350_TX_DTX_IDX0, | ||||
| 	[FE_REG_RX_BASE_PTR0] = RT5350_RX_BASE_PTR0, | ||||
| 	[FE_REG_RX_MAX_CNT0] = RT5350_RX_MAX_CNT0, | ||||
| 	[FE_REG_RX_CALC_IDX0] = RT5350_RX_CALC_IDX0, | ||||
| 	[FE_REG_RX_DRX_IDX0] = RT5350_RX_DRX_IDX0, | ||||
| 	[FE_REG_FE_INT_ENABLE] = RT5350_FE_INT_ENABLE, | ||||
| 	[FE_REG_FE_INT_STATUS] = RT5350_FE_INT_STATUS, | ||||
| 	[FE_REG_FE_DMA_VID_BASE] = 0, | ||||
| 	[FE_REG_FE_COUNTER_BASE] = MT7621_GDM1_TX_GBCNT, | ||||
| 	[FE_REG_FE_RST_GL] = MT7621_FE_RST_GL, | ||||
| 	[FE_REG_FE_INT_STATUS2] = MT7620_FE_INT_STATUS2, | ||||
| }; | ||||
|  | ||||
| static int mt7621_gsw_config(struct fe_priv *priv) | ||||
| { | ||||
| 	if (priv->mii_bus && priv->mii_bus->phy_map[0x1f]) | ||||
| 		mt7530_probe(priv->device, NULL, priv->mii_bus, 1); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static void mt7621_fe_reset(void) | ||||
| { | ||||
| 	fe_reset(MT7621_RESET_FE); | ||||
| } | ||||
|  | ||||
| static void mt7621_rxcsum_config(bool enable) | ||||
| { | ||||
| 	if (enable) | ||||
| 		fe_w32(fe_r32(MT7620A_GDMA1_FWD_CFG) | (GDMA_ICS_EN | | ||||
| 					GDMA_TCS_EN | GDMA_UCS_EN), | ||||
| 				MT7620A_GDMA1_FWD_CFG); | ||||
| 	else | ||||
| 		fe_w32(fe_r32(MT7620A_GDMA1_FWD_CFG) & ~(GDMA_ICS_EN | | ||||
| 					GDMA_TCS_EN | GDMA_UCS_EN), | ||||
| 				MT7620A_GDMA1_FWD_CFG); | ||||
| } | ||||
|  | ||||
| static void mt7621_rxvlan_config(bool enable) | ||||
| { | ||||
| 	if (enable) | ||||
| 		fe_w32(1, MT7621_CDMP_EG_CTRL); | ||||
| 	else | ||||
| 		fe_w32(0, MT7621_CDMP_EG_CTRL); | ||||
| } | ||||
|  | ||||
| static int mt7621_fwd_config(struct fe_priv *priv) | ||||
| { | ||||
| 	struct net_device *dev = priv_netdev(priv); | ||||
|  | ||||
| 	fe_w32(fe_r32(MT7620A_GDMA1_FWD_CFG) & ~0xffff, | ||||
| 	       MT7620A_GDMA1_FWD_CFG); | ||||
|  | ||||
| 	/* mt7621 doesn't have txcsum config */ | ||||
| 	mt7621_rxcsum_config((dev->features & NETIF_F_RXCSUM)); | ||||
| 	mt7621_rxvlan_config(priv->flags & FE_FLAG_RX_VLAN_CTAG); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static void mt7621_tx_dma(struct fe_tx_dma *txd) | ||||
| { | ||||
| 	txd->txd4 = MT7621_TX_DMA_FPORT; | ||||
| } | ||||
|  | ||||
| static void mt7621_init_data(struct fe_soc_data *data, | ||||
| 			     struct net_device *netdev) | ||||
| { | ||||
| 	struct fe_priv *priv = netdev_priv(netdev); | ||||
|  | ||||
| 	priv->flags = FE_FLAG_PADDING_64B | FE_FLAG_RX_2B_OFFSET | | ||||
| 		FE_FLAG_RX_SG_DMA | FE_FLAG_NAPI_WEIGHT | | ||||
| 		FE_FLAG_HAS_SWITCH; | ||||
|  | ||||
| 	netdev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM | | ||||
| 		NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_SG | NETIF_F_TSO | | ||||
| 		NETIF_F_TSO6 | NETIF_F_IPV6_CSUM; | ||||
| } | ||||
|  | ||||
| static void mt7621_set_mac(struct fe_priv *priv, unsigned char *mac) | ||||
| { | ||||
| 	unsigned long flags; | ||||
|  | ||||
| 	spin_lock_irqsave(&priv->page_lock, flags); | ||||
| 	fe_w32((mac[0] << 8) | mac[1], GSW_REG_GDMA1_MAC_ADRH); | ||||
| 	fe_w32((mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5], | ||||
| 	       GSW_REG_GDMA1_MAC_ADRL); | ||||
| 	spin_unlock_irqrestore(&priv->page_lock, flags); | ||||
| } | ||||
|  | ||||
| static struct fe_soc_data mt7621_data = { | ||||
| 	.init_data = mt7621_init_data, | ||||
| 	.reset_fe = mt7621_fe_reset, | ||||
| 	.set_mac = mt7621_set_mac, | ||||
| 	.fwd_config = mt7621_fwd_config, | ||||
| 	.tx_dma = mt7621_tx_dma, | ||||
| 	.switch_init = mtk_gsw_init, | ||||
| 	.switch_config = mt7621_gsw_config, | ||||
| 	.reg_table = mt7621_reg_table, | ||||
| 	.pdma_glo_cfg = FE_PDMA_SIZE_16DWORDS, | ||||
| 	.rx_int = RT5350_RX_DONE_INT, | ||||
| 	.tx_int = RT5350_TX_DONE_INT, | ||||
| 	.status_int = (MT7621_FE_GDM1_AF | MT7621_FE_GDM2_AF), | ||||
| 	.checksum_bit = MT7621_L4_VALID, | ||||
| 	.has_carrier = mt7620_has_carrier, | ||||
| 	.mdio_read = mt7620_mdio_read, | ||||
| 	.mdio_write = mt7620_mdio_write, | ||||
| 	.mdio_adjust_link = mt7620_mdio_link_adjust, | ||||
| }; | ||||
|  | ||||
| const struct of_device_id of_fe_match[] = { | ||||
| 	{ .compatible = "mediatek,mt7621-eth", .data = &mt7621_data }, | ||||
| 	{}, | ||||
| }; | ||||
|  | ||||
| MODULE_DEVICE_TABLE(of, of_fe_match); | ||||
| @@ -0,0 +1,76 @@ | ||||
| /*   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; version 2 of the License | ||||
|  * | ||||
|  *   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. | ||||
|  * | ||||
|  *   Copyright (C) 2009-2015 John Crispin <blogic@openwrt.org> | ||||
|  *   Copyright (C) 2009-2015 Felix Fietkau <nbd@nbd.name> | ||||
|  *   Copyright (C) 2013-2015 Michael Lee <igvtee@gmail.com> | ||||
|  */ | ||||
|  | ||||
| #include <linux/module.h> | ||||
|  | ||||
| #include <asm/mach-ralink/ralink_regs.h> | ||||
|  | ||||
| #include "mtk_eth_soc.h" | ||||
| #include "mdio_rt2880.h" | ||||
|  | ||||
| #define RT2880_RESET_FE			BIT(18) | ||||
|  | ||||
| static void rt2880_init_data(struct fe_soc_data *data, | ||||
| 			     struct net_device *netdev) | ||||
| { | ||||
| 	struct fe_priv *priv = netdev_priv(netdev); | ||||
|  | ||||
| 	priv->flags = FE_FLAG_PADDING_64B | FE_FLAG_PADDING_BUG | | ||||
| 		FE_FLAG_JUMBO_FRAME | FE_FLAG_CALIBRATE_CLK; | ||||
| 	netdev->hw_features = NETIF_F_SG | NETIF_F_HW_VLAN_CTAG_TX; | ||||
| 	/* this should work according to the datasheet but actually does not*/ | ||||
| 	/* netdev->hw_features |= NETIF_F_IP_CSUM | NETIF_F_RXCSUM; */ | ||||
| } | ||||
|  | ||||
| void rt2880_fe_reset(void) | ||||
| { | ||||
| 	fe_reset(RT2880_RESET_FE); | ||||
| } | ||||
|  | ||||
| static int rt2880_fwd_config(struct fe_priv *priv) | ||||
| { | ||||
| 	int ret; | ||||
|  | ||||
| 	ret = fe_set_clock_cycle(priv); | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
|  | ||||
| 	fe_fwd_config(priv); | ||||
| 	fe_w32(FE_PSE_FQFC_CFG_INIT, FE_PSE_FQ_CFG); | ||||
| 	fe_csum_config(priv); | ||||
|  | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| struct fe_soc_data rt2880_data = { | ||||
| 	.init_data = rt2880_init_data, | ||||
| 	.reset_fe = rt2880_fe_reset, | ||||
| 	.fwd_config = rt2880_fwd_config, | ||||
| 	.pdma_glo_cfg = FE_PDMA_SIZE_8DWORDS, | ||||
| 	.checksum_bit = RX_DMA_L4VALID, | ||||
| 	.rx_int = FE_RX_DONE_INT, | ||||
| 	.tx_int = FE_TX_DONE_INT, | ||||
| 	.status_int = FE_CNT_GDM_AF, | ||||
| 	.mdio_read = rt2880_mdio_read, | ||||
| 	.mdio_write = rt2880_mdio_write, | ||||
| 	.mdio_adjust_link = rt2880_mdio_link_adjust, | ||||
| 	.port_init = rt2880_port_init, | ||||
| }; | ||||
|  | ||||
| const struct of_device_id of_fe_match[] = { | ||||
| 	{ .compatible = "ralink,rt2880-eth", .data = &rt2880_data }, | ||||
| 	{}, | ||||
| }; | ||||
|  | ||||
| MODULE_DEVICE_TABLE(of, of_fe_match); | ||||
| @@ -0,0 +1,158 @@ | ||||
| /*   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; version 2 of the License | ||||
|  * | ||||
|  *   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. | ||||
|  * | ||||
|  *   Copyright (C) 2009-2015 John Crispin <blogic@openwrt.org> | ||||
|  *   Copyright (C) 2009-2015 Felix Fietkau <nbd@nbd.name> | ||||
|  *   Copyright (C) 2013-2015 Michael Lee <igvtee@gmail.com> | ||||
|  */ | ||||
|  | ||||
| #include <linux/module.h> | ||||
|  | ||||
| #include <asm/mach-ralink/ralink_regs.h> | ||||
|  | ||||
| #include "mtk_eth_soc.h" | ||||
| #include "mdio_rt2880.h" | ||||
|  | ||||
| #define RT305X_RESET_FE         BIT(21) | ||||
| #define RT305X_RESET_ESW        BIT(23) | ||||
|  | ||||
| static const u16 rt5350_reg_table[FE_REG_COUNT] = { | ||||
| 	[FE_REG_PDMA_GLO_CFG] = RT5350_PDMA_GLO_CFG, | ||||
| 	[FE_REG_PDMA_RST_CFG] = RT5350_PDMA_RST_CFG, | ||||
| 	[FE_REG_DLY_INT_CFG] = RT5350_DLY_INT_CFG, | ||||
| 	[FE_REG_TX_BASE_PTR0] = RT5350_TX_BASE_PTR0, | ||||
| 	[FE_REG_TX_MAX_CNT0] = RT5350_TX_MAX_CNT0, | ||||
| 	[FE_REG_TX_CTX_IDX0] = RT5350_TX_CTX_IDX0, | ||||
| 	[FE_REG_TX_DTX_IDX0] = RT5350_TX_DTX_IDX0, | ||||
| 	[FE_REG_RX_BASE_PTR0] = RT5350_RX_BASE_PTR0, | ||||
| 	[FE_REG_RX_MAX_CNT0] = RT5350_RX_MAX_CNT0, | ||||
| 	[FE_REG_RX_CALC_IDX0] = RT5350_RX_CALC_IDX0, | ||||
| 	[FE_REG_RX_DRX_IDX0] = RT5350_RX_DRX_IDX0, | ||||
| 	[FE_REG_FE_INT_ENABLE] = RT5350_FE_INT_ENABLE, | ||||
| 	[FE_REG_FE_INT_STATUS] = RT5350_FE_INT_STATUS, | ||||
| 	[FE_REG_FE_RST_GL] = 0, | ||||
| 	[FE_REG_FE_DMA_VID_BASE] = 0, | ||||
| }; | ||||
|  | ||||
| static void rt305x_init_data(struct fe_soc_data *data, | ||||
| 			     struct net_device *netdev) | ||||
| { | ||||
| 	struct fe_priv *priv = netdev_priv(netdev); | ||||
|  | ||||
| 	priv->flags = FE_FLAG_PADDING_64B | FE_FLAG_PADDING_BUG | | ||||
| 		FE_FLAG_CALIBRATE_CLK | FE_FLAG_HAS_SWITCH; | ||||
| 	netdev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | | ||||
| 		NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_TX; | ||||
| } | ||||
|  | ||||
| static int rt3050_fwd_config(struct fe_priv *priv) | ||||
| { | ||||
| 	int ret; | ||||
|  | ||||
| 	if (ralink_soc != RT305X_SOC_RT3052) { | ||||
| 		ret = fe_set_clock_cycle(priv); | ||||
| 		if (ret) | ||||
| 			return ret; | ||||
| 	} | ||||
|  | ||||
| 	fe_fwd_config(priv); | ||||
| 	if (ralink_soc != RT305X_SOC_RT3352) | ||||
| 		fe_w32(FE_PSE_FQFC_CFG_INIT, FE_PSE_FQ_CFG); | ||||
| 	fe_csum_config(priv); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static void rt305x_fe_reset(void) | ||||
| { | ||||
| 	fe_reset(RT305X_RESET_FE); | ||||
| } | ||||
|  | ||||
| static void rt5350_init_data(struct fe_soc_data *data, | ||||
| 			     struct net_device *netdev) | ||||
| { | ||||
| 	struct fe_priv *priv = netdev_priv(netdev); | ||||
|  | ||||
| 	priv->flags = FE_FLAG_HAS_SWITCH; | ||||
| 	netdev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM; | ||||
| } | ||||
|  | ||||
| static void rt5350_set_mac(struct fe_priv *priv, unsigned char *mac) | ||||
| { | ||||
| 	unsigned long flags; | ||||
|  | ||||
| 	spin_lock_irqsave(&priv->page_lock, flags); | ||||
| 	fe_w32((mac[0] << 8) | mac[1], RT5350_SDM_MAC_ADRH); | ||||
| 	fe_w32((mac[2] << 24) | (mac[3] << 16) | (mac[4] << 8) | mac[5], | ||||
| 	       RT5350_SDM_MAC_ADRL); | ||||
| 	spin_unlock_irqrestore(&priv->page_lock, flags); | ||||
| } | ||||
|  | ||||
| static void rt5350_rxcsum_config(bool enable) | ||||
| { | ||||
| 	if (enable) | ||||
| 		fe_w32(fe_r32(RT5350_SDM_CFG) | (RT5350_SDM_ICS_EN | | ||||
| 				RT5350_SDM_TCS_EN | RT5350_SDM_UCS_EN), | ||||
| 				RT5350_SDM_CFG); | ||||
| 	else | ||||
| 		fe_w32(fe_r32(RT5350_SDM_CFG) & ~(RT5350_SDM_ICS_EN | | ||||
| 				RT5350_SDM_TCS_EN | RT5350_SDM_UCS_EN), | ||||
| 				RT5350_SDM_CFG); | ||||
| } | ||||
|  | ||||
| static int rt5350_fwd_config(struct fe_priv *priv) | ||||
| { | ||||
| 	struct net_device *dev = priv_netdev(priv); | ||||
|  | ||||
| 	rt5350_rxcsum_config((dev->features & NETIF_F_RXCSUM)); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| static void rt5350_tx_dma(struct fe_tx_dma *txd) | ||||
| { | ||||
| 	txd->txd4 = 0; | ||||
| } | ||||
|  | ||||
| static void rt5350_fe_reset(void) | ||||
| { | ||||
| 	fe_reset(RT305X_RESET_FE | RT305X_RESET_ESW); | ||||
| } | ||||
|  | ||||
| static struct fe_soc_data rt3050_data = { | ||||
| 	.init_data = rt305x_init_data, | ||||
| 	.reset_fe = rt305x_fe_reset, | ||||
| 	.fwd_config = rt3050_fwd_config, | ||||
| 	.pdma_glo_cfg = FE_PDMA_SIZE_8DWORDS, | ||||
| 	.checksum_bit = RX_DMA_L4VALID, | ||||
| 	.rx_int = FE_RX_DONE_INT, | ||||
| 	.tx_int = FE_TX_DONE_INT, | ||||
| 	.status_int = FE_CNT_GDM_AF, | ||||
| }; | ||||
|  | ||||
| static struct fe_soc_data rt5350_data = { | ||||
| 	.init_data = rt5350_init_data, | ||||
| 	.reg_table = rt5350_reg_table, | ||||
| 	.reset_fe = rt5350_fe_reset, | ||||
| 	.set_mac = rt5350_set_mac, | ||||
| 	.fwd_config = rt5350_fwd_config, | ||||
| 	.tx_dma = rt5350_tx_dma, | ||||
| 	.pdma_glo_cfg = FE_PDMA_SIZE_8DWORDS, | ||||
| 	.checksum_bit = RX_DMA_L4VALID, | ||||
| 	.rx_int = RT5350_RX_DONE_INT, | ||||
| 	.tx_int = RT5350_TX_DONE_INT, | ||||
| }; | ||||
|  | ||||
| const struct of_device_id of_fe_match[] = { | ||||
| 	{ .compatible = "ralink,rt3050-eth", .data = &rt3050_data }, | ||||
| 	{ .compatible = "ralink,rt5350-eth", .data = &rt5350_data }, | ||||
| 	{}, | ||||
| }; | ||||
|  | ||||
| MODULE_DEVICE_TABLE(of, of_fe_match); | ||||
| @@ -0,0 +1,75 @@ | ||||
| /*   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; version 2 of the License | ||||
|  * | ||||
|  *   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. | ||||
|  * | ||||
|  *   Copyright (C) 2009-2015 John Crispin <blogic@openwrt.org> | ||||
|  *   Copyright (C) 2009-2015 Felix Fietkau <nbd@nbd.name> | ||||
|  *   Copyright (C) 2013-2015 Michael Lee <igvtee@gmail.com> | ||||
|  */ | ||||
|  | ||||
| #include <linux/module.h> | ||||
|  | ||||
| #include <asm/mach-ralink/ralink_regs.h> | ||||
|  | ||||
| #include "mtk_eth_soc.h" | ||||
| #include "mdio_rt2880.h" | ||||
|  | ||||
| #define RT3883_RSTCTRL_FE		BIT(21) | ||||
|  | ||||
| static void rt3883_fe_reset(void) | ||||
| { | ||||
| 	fe_reset(RT3883_RSTCTRL_FE); | ||||
| } | ||||
|  | ||||
| static int rt3883_fwd_config(struct fe_priv *priv) | ||||
| { | ||||
| 	int ret; | ||||
|  | ||||
| 	ret = fe_set_clock_cycle(priv); | ||||
| 	if (ret) | ||||
| 		return ret; | ||||
|  | ||||
| 	fe_fwd_config(priv); | ||||
| 	fe_w32(FE_PSE_FQFC_CFG_256Q, FE_PSE_FQ_CFG); | ||||
| 	fe_csum_config(priv); | ||||
|  | ||||
| 	return ret; | ||||
| } | ||||
|  | ||||
| static void rt3883_init_data(struct fe_soc_data *data, | ||||
| 			     struct net_device *netdev) | ||||
| { | ||||
| 	struct fe_priv *priv = netdev_priv(netdev); | ||||
|  | ||||
| 	priv->flags = FE_FLAG_PADDING_64B | FE_FLAG_PADDING_BUG | | ||||
| 		FE_FLAG_JUMBO_FRAME | FE_FLAG_CALIBRATE_CLK; | ||||
| 	netdev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | | ||||
| 		NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_TX; | ||||
| } | ||||
|  | ||||
| static struct fe_soc_data rt3883_data = { | ||||
| 	.init_data = rt3883_init_data, | ||||
| 	.reset_fe = rt3883_fe_reset, | ||||
| 	.fwd_config = rt3883_fwd_config, | ||||
| 	.pdma_glo_cfg = FE_PDMA_SIZE_8DWORDS, | ||||
| 	.rx_int = FE_RX_DONE_INT, | ||||
| 	.tx_int = FE_TX_DONE_INT, | ||||
| 	.status_int = FE_CNT_GDM_AF, | ||||
| 	.checksum_bit = RX_DMA_L4VALID, | ||||
| 	.mdio_read = rt2880_mdio_read, | ||||
| 	.mdio_write = rt2880_mdio_write, | ||||
| 	.mdio_adjust_link = rt2880_mdio_link_adjust, | ||||
| 	.port_init = rt2880_port_init, | ||||
| }; | ||||
|  | ||||
| const struct of_device_id of_fe_match[] = { | ||||
| 	{ .compatible = "ralink,rt3883-eth", .data = &rt3883_data }, | ||||
| 	{}, | ||||
| }; | ||||
|  | ||||
| MODULE_DEVICE_TABLE(of, of_fe_match); | ||||
							
								
								
									
										215
									
								
								target/linux/ramips/mt7620/config-4.9
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										215
									
								
								target/linux/ramips/mt7620/config-4.9
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,215 @@ | ||||
| CONFIG_ARCH_BINFMT_ELF_STATE=y | ||||
| CONFIG_ARCH_CLOCKSOURCE_DATA=y | ||||
| CONFIG_ARCH_DISCARD_MEMBLOCK=y | ||||
| CONFIG_ARCH_HAS_ELF_RANDOMIZE=y | ||||
| # CONFIG_ARCH_HAS_GCOV_PROFILE_ALL is not set | ||||
| CONFIG_ARCH_HAS_RESET_CONTROLLER=y | ||||
| # CONFIG_ARCH_HAS_SG_CHAIN is not set | ||||
| CONFIG_ARCH_HIBERNATION_POSSIBLE=y | ||||
| CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y | ||||
| CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y | ||||
| CONFIG_ARCH_SUPPORTS_UPROBES=y | ||||
| CONFIG_ARCH_SUSPEND_POSSIBLE=y | ||||
| CONFIG_ARCH_USE_BUILTIN_BSWAP=y | ||||
| CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y | ||||
| CONFIG_AT803X_PHY=y | ||||
| CONFIG_BLK_MQ_PCI=y | ||||
| CONFIG_CEVT_R4K=y | ||||
| CONFIG_CEVT_SYSTICK_QUIRK=y | ||||
| CONFIG_CLKDEV_LOOKUP=y | ||||
| CONFIG_CLKEVT_RT3352=y | ||||
| CONFIG_CLKSRC_MMIO=y | ||||
| CONFIG_CLKSRC_OF=y | ||||
| CONFIG_CLKSRC_PROBE=y | ||||
| CONFIG_CLONE_BACKWARDS=y | ||||
| CONFIG_CMDLINE="rootfstype=squashfs,jffs2" | ||||
| CONFIG_CMDLINE_BOOL=y | ||||
| # CONFIG_CMDLINE_OVERRIDE is not set | ||||
| CONFIG_CPU_GENERIC_DUMP_TLB=y | ||||
| CONFIG_CPU_HAS_PREFETCH=y | ||||
| CONFIG_CPU_HAS_RIXI=y | ||||
| CONFIG_CPU_HAS_SYNC=y | ||||
| CONFIG_CPU_LITTLE_ENDIAN=y | ||||
| CONFIG_CPU_MIPS32=y | ||||
| # CONFIG_CPU_MIPS32_R1 is not set | ||||
| CONFIG_CPU_MIPS32_R2=y | ||||
| CONFIG_CPU_MIPSR2=y | ||||
| CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y | ||||
| CONFIG_CPU_R4K_CACHE_TLB=y | ||||
| CONFIG_CPU_R4K_FPU=y | ||||
| CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y | ||||
| CONFIG_CPU_SUPPORTS_HIGHMEM=y | ||||
| CONFIG_CPU_SUPPORTS_MSA=y | ||||
| CONFIG_CRYPTO_RNG2=y | ||||
| CONFIG_CRYPTO_WORKQUEUE=y | ||||
| CONFIG_CSRC_R4K=y | ||||
| CONFIG_DEBUG_PINCTRL=y | ||||
| CONFIG_DMA_NONCOHERENT=y | ||||
| # CONFIG_DTB_MT7620A_EVAL is not set | ||||
| CONFIG_DTB_RT_NONE=y | ||||
| CONFIG_DTC=y | ||||
| CONFIG_EARLY_PRINTK=y | ||||
| CONFIG_FIXED_PHY=y | ||||
| CONFIG_GENERIC_ATOMIC64=y | ||||
| CONFIG_GENERIC_CLOCKEVENTS=y | ||||
| CONFIG_GENERIC_CMOS_UPDATE=y | ||||
| CONFIG_GENERIC_IO=y | ||||
| CONFIG_GENERIC_IRQ_CHIP=y | ||||
| CONFIG_GENERIC_IRQ_SHOW=y | ||||
| CONFIG_GENERIC_PCI_IOMAP=y | ||||
| CONFIG_GENERIC_PHY=y | ||||
| CONFIG_GENERIC_SCHED_CLOCK=y | ||||
| CONFIG_GENERIC_SMP_IDLE_THREAD=y | ||||
| CONFIG_GENERIC_TIME_VSYSCALL=y | ||||
| CONFIG_GPIOLIB=y | ||||
| # CONFIG_GPIO_MT7621 is not set | ||||
| CONFIG_GPIO_RALINK=y | ||||
| CONFIG_GPIO_SYSFS=y | ||||
| CONFIG_HANDLE_DOMAIN_IRQ=y | ||||
| CONFIG_HARDWARE_WATCHPOINTS=y | ||||
| CONFIG_HAS_DMA=y | ||||
| CONFIG_HAS_IOMEM=y | ||||
| CONFIG_HAS_IOPORT_MAP=y | ||||
| # CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set | ||||
| # CONFIG_HAVE_ARCH_BITREVERSE is not set | ||||
| CONFIG_HAVE_ARCH_JUMP_LABEL=y | ||||
| CONFIG_HAVE_ARCH_KGDB=y | ||||
| CONFIG_HAVE_ARCH_SECCOMP_FILTER=y | ||||
| CONFIG_HAVE_ARCH_TRACEHOOK=y | ||||
| # CONFIG_HAVE_BOOTMEM_INFO_NODE is not set | ||||
| CONFIG_HAVE_CBPF_JIT=y | ||||
| CONFIG_HAVE_CC_STACKPROTECTOR=y | ||||
| CONFIG_HAVE_CLK=y | ||||
| CONFIG_HAVE_CONTEXT_TRACKING=y | ||||
| CONFIG_HAVE_C_RECORDMCOUNT=y | ||||
| CONFIG_HAVE_DEBUG_KMEMLEAK=y | ||||
| CONFIG_HAVE_DEBUG_STACKOVERFLOW=y | ||||
| CONFIG_HAVE_DMA_API_DEBUG=y | ||||
| CONFIG_HAVE_DMA_CONTIGUOUS=y | ||||
| CONFIG_HAVE_DYNAMIC_FTRACE=y | ||||
| CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y | ||||
| CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y | ||||
| CONFIG_HAVE_FUNCTION_TRACER=y | ||||
| CONFIG_HAVE_GENERIC_DMA_COHERENT=y | ||||
| CONFIG_HAVE_IDE=y | ||||
| CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y | ||||
| CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y | ||||
| CONFIG_HAVE_KVM=y | ||||
| CONFIG_HAVE_LATENCYTOP_SUPPORT=y | ||||
| CONFIG_HAVE_MEMBLOCK=y | ||||
| CONFIG_HAVE_MEMBLOCK_NODE_MAP=y | ||||
| CONFIG_HAVE_MOD_ARCH_SPECIFIC=y | ||||
| CONFIG_HAVE_NET_DSA=y | ||||
| CONFIG_HAVE_OPROFILE=y | ||||
| CONFIG_HAVE_PERF_EVENTS=y | ||||
| CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y | ||||
| CONFIG_HAVE_SYSCALL_TRACEPOINTS=y | ||||
| CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y | ||||
| CONFIG_HW_HAS_PCI=y | ||||
| CONFIG_HZ_PERIODIC=y | ||||
| CONFIG_ICPLUS_PHY=y | ||||
| CONFIG_INITRAMFS_SOURCE="" | ||||
| CONFIG_IRQCHIP=y | ||||
| CONFIG_IRQ_DOMAIN=y | ||||
| CONFIG_IRQ_FORCED_THREADING=y | ||||
| CONFIG_IRQ_INTC=y | ||||
| CONFIG_IRQ_MIPS_CPU=y | ||||
| CONFIG_IRQ_WORK=y | ||||
| CONFIG_LIBFDT=y | ||||
| CONFIG_MDIO_BOARDINFO=y | ||||
| CONFIG_MIPS=y | ||||
| CONFIG_MIPS_ASID_BITS=8 | ||||
| CONFIG_MIPS_ASID_SHIFT=0 | ||||
| CONFIG_MIPS_CLOCK_VSYSCALL=y | ||||
| # CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND is not set | ||||
| # CONFIG_MIPS_CMDLINE_DTB_EXTEND is not set | ||||
| # CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set | ||||
| CONFIG_MIPS_CMDLINE_FROM_DTB=y | ||||
| # CONFIG_MIPS_ELF_APPENDED_DTB is not set | ||||
| # CONFIG_MIPS_HUGE_TLB_SUPPORT is not set | ||||
| CONFIG_MIPS_L1_CACHE_SHIFT=5 | ||||
| # CONFIG_MIPS_MACHINE is not set | ||||
| CONFIG_MIPS_NO_APPENDED_DTB=y | ||||
| # CONFIG_MIPS_RAW_APPENDED_DTB is not set | ||||
| CONFIG_MIPS_SPRAM=y | ||||
| CONFIG_MODULES_USE_ELF_REL=y | ||||
| # CONFIG_MT7621_WDT is not set | ||||
| # CONFIG_MTD_CFI_INTELEXT is not set | ||||
| CONFIG_MTD_CMDLINE_PARTS=y | ||||
| CONFIG_MTD_M25P80=y | ||||
| CONFIG_MTD_NAND_MT7620=y | ||||
| CONFIG_MTD_PHYSMAP=y | ||||
| CONFIG_MTD_SPI_NOR=y | ||||
| CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y | ||||
| CONFIG_MTD_SPLIT_FIRMWARE=y | ||||
| CONFIG_MTD_SPLIT_SEAMA_FW=y | ||||
| CONFIG_MTD_SPLIT_TPLINK_FW=y | ||||
| CONFIG_MTD_SPLIT_UIMAGE_FW=y | ||||
| CONFIG_NEED_DMA_MAP_STATE=y | ||||
| CONFIG_NEED_PER_CPU_KM=y | ||||
| CONFIG_NET_MEDIATEK_GSW_MT7620=y | ||||
| CONFIG_NET_MEDIATEK_MDIO=y | ||||
| CONFIG_NET_MEDIATEK_MDIO_MT7620=y | ||||
| CONFIG_NET_MEDIATEK_MT7620=y | ||||
| # CONFIG_NET_MEDIATEK_RT3050 is not set | ||||
| CONFIG_NET_MEDIATEK_SOC=y | ||||
| CONFIG_NET_VENDOR_MEDIATEK=y | ||||
| CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y | ||||
| # CONFIG_NO_IOPORT_MAP is not set | ||||
| CONFIG_OF=y | ||||
| CONFIG_OF_ADDRESS=y | ||||
| CONFIG_OF_ADDRESS_PCI=y | ||||
| CONFIG_OF_EARLY_FLATTREE=y | ||||
| CONFIG_OF_FLATTREE=y | ||||
| CONFIG_OF_GPIO=y | ||||
| CONFIG_OF_IRQ=y | ||||
| CONFIG_OF_MDIO=y | ||||
| CONFIG_OF_NET=y | ||||
| CONFIG_OF_PCI=y | ||||
| CONFIG_OF_PCI_IRQ=y | ||||
| CONFIG_PCI=y | ||||
| CONFIG_PCI_DOMAINS=y | ||||
| CONFIG_PCI_DRIVERS_LEGACY=y | ||||
| CONFIG_PERF_USE_VMALLOC=y | ||||
| CONFIG_PGTABLE_LEVELS=2 | ||||
| CONFIG_PHYLIB=y | ||||
| CONFIG_PHY_RALINK_USB=y | ||||
| CONFIG_PINCTRL=y | ||||
| CONFIG_PINCTRL_RT2880=y | ||||
| # CONFIG_PINCTRL_SINGLE is not set | ||||
| CONFIG_RALINK=y | ||||
| CONFIG_RALINK_WDT=y | ||||
| # CONFIG_RCU_STALL_COMMON is not set | ||||
| CONFIG_RESET_CONTROLLER=y | ||||
| CONFIG_SCHED_HRTICK=y | ||||
| # CONFIG_SCHED_INFO is not set | ||||
| # CONFIG_SCSI_DMA is not set | ||||
| # CONFIG_SERIAL_8250_FSL is not set | ||||
| CONFIG_SERIAL_8250_RT288X=y | ||||
| CONFIG_SERIAL_OF_PLATFORM=y | ||||
| # CONFIG_SG_POOL is not set | ||||
| CONFIG_SOC_MT7620=y | ||||
| # CONFIG_SOC_MT7621 is not set | ||||
| # CONFIG_SOC_RT288X is not set | ||||
| # CONFIG_SOC_RT305X is not set | ||||
| # CONFIG_SOC_RT3883 is not set | ||||
| CONFIG_SPI=y | ||||
| CONFIG_SPI_MASTER=y | ||||
| # CONFIG_SPI_MT7621 is not set | ||||
| CONFIG_SPI_RT2880=y | ||||
| CONFIG_SRCU=y | ||||
| CONFIG_SWCONFIG=y | ||||
| CONFIG_SWCONFIG_LEDS=y | ||||
| CONFIG_SWPHY=y | ||||
| CONFIG_SYSCTL_EXCEPTION_TRACE=y | ||||
| CONFIG_SYS_HAS_CPU_MIPS32_R1=y | ||||
| CONFIG_SYS_HAS_CPU_MIPS32_R2=y | ||||
| CONFIG_SYS_HAS_EARLY_PRINTK=y | ||||
| CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y | ||||
| CONFIG_SYS_SUPPORTS_ARBIT_HZ=y | ||||
| CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y | ||||
| CONFIG_SYS_SUPPORTS_MIPS16=y | ||||
| CONFIG_TICK_CPU_ACCOUNTING=y | ||||
| CONFIG_USB_SUPPORT=y | ||||
| CONFIG_USE_OF=y | ||||
| CONFIG_WATCHDOG_CORE=y | ||||
| @@ -46,8 +46,14 @@ CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y | ||||
| CONFIG_CPU_SUPPORTS_HIGHMEM=y | ||||
| CONFIG_CPU_SUPPORTS_MSA=y | ||||
| CONFIG_CRC16=y | ||||
| CONFIG_CRYPTO_AEAD=y | ||||
| CONFIG_CRYPTO_AEAD2=y | ||||
| CONFIG_CRYPTO_DEFLATE=y | ||||
| CONFIG_CRYPTO_HASH2=y | ||||
| CONFIG_CRYPTO_LZO=y | ||||
| CONFIG_CRYPTO_MANAGER=y | ||||
| CONFIG_CRYPTO_MANAGER2=y | ||||
| CONFIG_CRYPTO_NULL2=y | ||||
| CONFIG_CRYPTO_RNG2=y | ||||
| CONFIG_CRYPTO_WORKQUEUE=y | ||||
| CONFIG_CSRC_R4K=y | ||||
| @@ -100,6 +106,7 @@ CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y | ||||
| CONFIG_HAVE_FUNCTION_TRACER=y | ||||
| CONFIG_HAVE_GENERIC_DMA_COHERENT=y | ||||
| CONFIG_HAVE_IDE=y | ||||
| CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y | ||||
| CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y | ||||
| CONFIG_HAVE_KVM=y | ||||
| CONFIG_HAVE_LATENCYTOP_SUPPORT=y | ||||
| @@ -116,8 +123,8 @@ CONFIG_HIGHMEM=y | ||||
| CONFIG_HW_HAS_PCI=y | ||||
| CONFIG_HZ_PERIODIC=y | ||||
| CONFIG_I2C=y | ||||
| CONFIG_I2C_BOARDINFO=y | ||||
| CONFIG_I2C_MT7621=y | ||||
| # CONFIG_IMG_MDC_DMA is not set | ||||
| CONFIG_INITRAMFS_SOURCE="" | ||||
| CONFIG_IRQCHIP=y | ||||
| CONFIG_IRQ_DOMAIN=y | ||||
| @@ -195,6 +202,7 @@ CONFIG_OF_MTD=y | ||||
| CONFIG_OF_NET=y | ||||
| CONFIG_OF_PCI=y | ||||
| CONFIG_OF_PCI_IRQ=y | ||||
| CONFIG_PADATA=y | ||||
| CONFIG_PCI=y | ||||
| CONFIG_PCI_DISABLE_COMMON_QUIRKS=y | ||||
| CONFIG_PCI_DOMAINS=y | ||||
|   | ||||
							
								
								
									
										279
									
								
								target/linux/ramips/mt7621/config-4.9
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										279
									
								
								target/linux/ramips/mt7621/config-4.9
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,279 @@ | ||||
| CONFIG_ARCH_BINFMT_ELF_STATE=y | ||||
| CONFIG_ARCH_CLOCKSOURCE_DATA=y | ||||
| CONFIG_ARCH_DISCARD_MEMBLOCK=y | ||||
| CONFIG_ARCH_HAS_ELF_RANDOMIZE=y | ||||
| # CONFIG_ARCH_HAS_GCOV_PROFILE_ALL is not set | ||||
| CONFIG_ARCH_HAS_RESET_CONTROLLER=y | ||||
| # CONFIG_ARCH_HAS_SG_CHAIN is not set | ||||
| CONFIG_ARCH_HIBERNATION_POSSIBLE=y | ||||
| CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y | ||||
| CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y | ||||
| CONFIG_ARCH_SUPPORTS_UPROBES=y | ||||
| CONFIG_ARCH_SUSPEND_POSSIBLE=y | ||||
| CONFIG_ARCH_USE_BUILTIN_BSWAP=y | ||||
| CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y | ||||
| CONFIG_BLK_MQ_PCI=y | ||||
| CONFIG_BOARD_SCACHE=y | ||||
| CONFIG_BOUNCE=y | ||||
| CONFIG_CEVT_R4K=y | ||||
| # CONFIG_CEVT_SYSTICK_QUIRK is not set | ||||
| CONFIG_CLKDEV_LOOKUP=y | ||||
| CONFIG_CLKSRC_MIPS_GIC=y | ||||
| CONFIG_CLKSRC_OF=y | ||||
| CONFIG_CLKSRC_PROBE=y | ||||
| CONFIG_CLONE_BACKWARDS=y | ||||
| CONFIG_CMDLINE="rootfstype=squashfs,jffs2" | ||||
| CONFIG_CMDLINE_BOOL=y | ||||
| # CONFIG_CMDLINE_OVERRIDE is not set | ||||
| CONFIG_COMMON_CLK=y | ||||
| CONFIG_CPU_GENERIC_DUMP_TLB=y | ||||
| CONFIG_CPU_HAS_PREFETCH=y | ||||
| CONFIG_CPU_HAS_RIXI=y | ||||
| CONFIG_CPU_HAS_SYNC=y | ||||
| CONFIG_CPU_LITTLE_ENDIAN=y | ||||
| CONFIG_CPU_MIPS32=y | ||||
| # CONFIG_CPU_MIPS32_R1 is not set | ||||
| CONFIG_CPU_MIPS32_R2=y | ||||
| CONFIG_CPU_MIPSR2=y | ||||
| CONFIG_CPU_MIPSR2_IRQ_EI=y | ||||
| CONFIG_CPU_MIPSR2_IRQ_VI=y | ||||
| CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y | ||||
| CONFIG_CPU_R4K_CACHE_TLB=y | ||||
| CONFIG_CPU_R4K_FPU=y | ||||
| CONFIG_CPU_RMAP=y | ||||
| CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y | ||||
| CONFIG_CPU_SUPPORTS_HIGHMEM=y | ||||
| CONFIG_CPU_SUPPORTS_MSA=y | ||||
| CONFIG_CRC16=y | ||||
| CONFIG_CRYPTO_AEAD=y | ||||
| CONFIG_CRYPTO_AEAD2=y | ||||
| CONFIG_CRYPTO_DEFLATE=y | ||||
| CONFIG_CRYPTO_HASH2=y | ||||
| CONFIG_CRYPTO_LZO=y | ||||
| CONFIG_CRYPTO_MANAGER=y | ||||
| CONFIG_CRYPTO_MANAGER2=y | ||||
| CONFIG_CRYPTO_NULL2=y | ||||
| CONFIG_CRYPTO_RNG2=y | ||||
| CONFIG_CRYPTO_WORKQUEUE=y | ||||
| CONFIG_CSRC_R4K=y | ||||
| CONFIG_DEBUG_PINCTRL=y | ||||
| CONFIG_DMA_NONCOHERENT=y | ||||
| CONFIG_DTB_RT_NONE=y | ||||
| CONFIG_DTC=y | ||||
| CONFIG_EARLY_PRINTK=y | ||||
| CONFIG_FIXED_PHY=y | ||||
| CONFIG_GENERIC_ATOMIC64=y | ||||
| CONFIG_GENERIC_CLOCKEVENTS=y | ||||
| CONFIG_GENERIC_CMOS_UPDATE=y | ||||
| CONFIG_GENERIC_IO=y | ||||
| CONFIG_GENERIC_IRQ_CHIP=y | ||||
| CONFIG_GENERIC_IRQ_IPI=y | ||||
| CONFIG_GENERIC_IRQ_SHOW=y | ||||
| CONFIG_GENERIC_PCI_IOMAP=y | ||||
| CONFIG_GENERIC_SCHED_CLOCK=y | ||||
| CONFIG_GENERIC_SMP_IDLE_THREAD=y | ||||
| CONFIG_GENERIC_TIME_VSYSCALL=y | ||||
| CONFIG_GPIOLIB=y | ||||
| CONFIG_GPIO_MT7621=y | ||||
| # CONFIG_GPIO_RALINK is not set | ||||
| CONFIG_GPIO_SYSFS=y | ||||
| CONFIG_HANDLE_DOMAIN_IRQ=y | ||||
| CONFIG_HARDWARE_WATCHPOINTS=y | ||||
| CONFIG_HAS_DMA=y | ||||
| CONFIG_HAS_IOMEM=y | ||||
| CONFIG_HAS_IOPORT_MAP=y | ||||
| # CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set | ||||
| # CONFIG_HAVE_ARCH_BITREVERSE is not set | ||||
| CONFIG_HAVE_ARCH_JUMP_LABEL=y | ||||
| CONFIG_HAVE_ARCH_KGDB=y | ||||
| CONFIG_HAVE_ARCH_SECCOMP_FILTER=y | ||||
| CONFIG_HAVE_ARCH_TRACEHOOK=y | ||||
| # CONFIG_HAVE_BOOTMEM_INFO_NODE is not set | ||||
| CONFIG_HAVE_CBPF_JIT=y | ||||
| CONFIG_HAVE_CC_STACKPROTECTOR=y | ||||
| CONFIG_HAVE_CLK=y | ||||
| CONFIG_HAVE_CLK_PREPARE=y | ||||
| CONFIG_HAVE_CONTEXT_TRACKING=y | ||||
| CONFIG_HAVE_C_RECORDMCOUNT=y | ||||
| CONFIG_HAVE_DEBUG_KMEMLEAK=y | ||||
| CONFIG_HAVE_DEBUG_STACKOVERFLOW=y | ||||
| CONFIG_HAVE_DMA_API_DEBUG=y | ||||
| CONFIG_HAVE_DMA_CONTIGUOUS=y | ||||
| CONFIG_HAVE_DYNAMIC_FTRACE=y | ||||
| CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y | ||||
| CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y | ||||
| CONFIG_HAVE_FUNCTION_TRACER=y | ||||
| CONFIG_HAVE_GENERIC_DMA_COHERENT=y | ||||
| CONFIG_HAVE_IDE=y | ||||
| CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y | ||||
| CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y | ||||
| CONFIG_HAVE_KVM=y | ||||
| CONFIG_HAVE_LATENCYTOP_SUPPORT=y | ||||
| CONFIG_HAVE_MEMBLOCK=y | ||||
| CONFIG_HAVE_MEMBLOCK_NODE_MAP=y | ||||
| CONFIG_HAVE_MOD_ARCH_SPECIFIC=y | ||||
| CONFIG_HAVE_NET_DSA=y | ||||
| CONFIG_HAVE_OPROFILE=y | ||||
| CONFIG_HAVE_PERF_EVENTS=y | ||||
| CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y | ||||
| CONFIG_HAVE_SYSCALL_TRACEPOINTS=y | ||||
| CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y | ||||
| CONFIG_HIGHMEM=y | ||||
| CONFIG_HW_HAS_PCI=y | ||||
| CONFIG_HZ_PERIODIC=y | ||||
| CONFIG_I2C=y | ||||
| CONFIG_I2C_BOARDINFO=y | ||||
| CONFIG_I2C_MT7621=y | ||||
| CONFIG_INITRAMFS_SOURCE="" | ||||
| CONFIG_IRQCHIP=y | ||||
| CONFIG_IRQ_DOMAIN=y | ||||
| CONFIG_IRQ_DOMAIN_HIERARCHY=y | ||||
| CONFIG_IRQ_FORCED_THREADING=y | ||||
| CONFIG_IRQ_MIPS_CPU=y | ||||
| CONFIG_IRQ_WORK=y | ||||
| CONFIG_LIBFDT=y | ||||
| CONFIG_LZO_COMPRESS=y | ||||
| CONFIG_LZO_DECOMPRESS=y | ||||
| CONFIG_MDIO_BOARDINFO=y | ||||
| # CONFIG_MFD_MAX77620 is not set | ||||
| CONFIG_MIPS=y | ||||
| CONFIG_MIPS_ASID_BITS=8 | ||||
| CONFIG_MIPS_ASID_SHIFT=0 | ||||
| CONFIG_MIPS_CLOCK_VSYSCALL=y | ||||
| CONFIG_MIPS_CM=y | ||||
| # CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND is not set | ||||
| # CONFIG_MIPS_CMDLINE_DTB_EXTEND is not set | ||||
| # CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set | ||||
| CONFIG_MIPS_CMDLINE_FROM_DTB=y | ||||
| CONFIG_MIPS_CPC=y | ||||
| CONFIG_MIPS_CPS=y | ||||
| # CONFIG_MIPS_CPS_NS16550 is not set | ||||
| CONFIG_MIPS_CPU_SCACHE=y | ||||
| # CONFIG_MIPS_ELF_APPENDED_DTB is not set | ||||
| CONFIG_MIPS_GIC=y | ||||
| # CONFIG_MIPS_HUGE_TLB_SUPPORT is not set | ||||
| CONFIG_MIPS_L1_CACHE_SHIFT=5 | ||||
| # CONFIG_MIPS_MACHINE is not set | ||||
| CONFIG_MIPS_MT=y | ||||
| CONFIG_MIPS_MT_FPAFF=y | ||||
| CONFIG_MIPS_MT_SMP=y | ||||
| CONFIG_MIPS_NO_APPENDED_DTB=y | ||||
| CONFIG_MIPS_PERF_SHARED_TC_COUNTERS=y | ||||
| # CONFIG_MIPS_RAW_APPENDED_DTB is not set | ||||
| CONFIG_MIPS_SPRAM=y | ||||
| # CONFIG_MIPS_VPE_LOADER is not set | ||||
| CONFIG_MODULES_USE_ELF_REL=y | ||||
| CONFIG_MT7621_WDT=y | ||||
| # CONFIG_MTD_CFI_INTELEXT is not set | ||||
| CONFIG_MTD_CMDLINE_PARTS=y | ||||
| CONFIG_MTD_M25P80=y | ||||
| CONFIG_MTD_NAND=y | ||||
| CONFIG_MTD_NAND_ECC=y | ||||
| CONFIG_MTD_PHYSMAP=y | ||||
| CONFIG_MTD_SPI_NOR=y | ||||
| CONFIG_MTD_SPLIT_FIRMWARE=y | ||||
| CONFIG_MTD_SPLIT_SEAMA_FW=y | ||||
| CONFIG_MTD_SPLIT_TRX_FW=y | ||||
| CONFIG_MTD_SPLIT_UIMAGE_FW=y | ||||
| CONFIG_MTD_UBI=y | ||||
| CONFIG_MTD_UBI_BEB_LIMIT=20 | ||||
| CONFIG_MTD_UBI_BLOCK=y | ||||
| # CONFIG_MTD_UBI_FASTMAP is not set | ||||
| # CONFIG_MTD_UBI_GLUEBI is not set | ||||
| CONFIG_MTD_UBI_WL_THRESHOLD=4096 | ||||
| CONFIG_NEED_DMA_MAP_STATE=y | ||||
| CONFIG_NET_FLOW_LIMIT=y | ||||
| CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y | ||||
| # CONFIG_NO_IOPORT_MAP is not set | ||||
| CONFIG_NR_CPUS=4 | ||||
| CONFIG_OF=y | ||||
| CONFIG_OF_ADDRESS=y | ||||
| CONFIG_OF_ADDRESS_PCI=y | ||||
| CONFIG_OF_EARLY_FLATTREE=y | ||||
| CONFIG_OF_FLATTREE=y | ||||
| CONFIG_OF_GPIO=y | ||||
| CONFIG_OF_IRQ=y | ||||
| CONFIG_OF_MDIO=y | ||||
| CONFIG_OF_NET=y | ||||
| CONFIG_OF_PCI=y | ||||
| CONFIG_OF_PCI_IRQ=y | ||||
| CONFIG_PADATA=y | ||||
| CONFIG_PCI=y | ||||
| CONFIG_PCI_DISABLE_COMMON_QUIRKS=y | ||||
| CONFIG_PCI_DOMAINS=y | ||||
| CONFIG_PCI_DRIVERS_LEGACY=y | ||||
| CONFIG_PERF_USE_VMALLOC=y | ||||
| CONFIG_PGTABLE_LEVELS=2 | ||||
| CONFIG_PHYLIB=y | ||||
| # CONFIG_PHY_RALINK_USB is not set | ||||
| CONFIG_PINCTRL=y | ||||
| CONFIG_PINCTRL_RT2880=y | ||||
| # CONFIG_PINCTRL_SINGLE is not set | ||||
| CONFIG_POWER_RESET=y | ||||
| CONFIG_POWER_RESET_GPIO=y | ||||
| CONFIG_POWER_SUPPLY=y | ||||
| CONFIG_RALINK=y | ||||
| # CONFIG_RALINK_WDT is not set | ||||
| CONFIG_RATIONAL=y | ||||
| CONFIG_RCU_STALL_COMMON=y | ||||
| CONFIG_REGMAP=y | ||||
| CONFIG_REGMAP_I2C=y | ||||
| CONFIG_REGMAP_SPI=y | ||||
| CONFIG_RESET_CONTROLLER=y | ||||
| CONFIG_RFS_ACCEL=y | ||||
| CONFIG_RPS=y | ||||
| CONFIG_RTC_CLASS=y | ||||
| CONFIG_RTC_DRV_PCF8563=y | ||||
| CONFIG_RTC_I2C_AND_SPI=y | ||||
| CONFIG_RTC_MC146818_LIB=y | ||||
| CONFIG_SCHED_HRTICK=y | ||||
| # CONFIG_SCHED_INFO is not set | ||||
| CONFIG_SCHED_SMT=y | ||||
| # CONFIG_SCSI_DMA is not set | ||||
| # CONFIG_SERIAL_8250_FSL is not set | ||||
| CONFIG_SERIAL_8250_NR_UARTS=3 | ||||
| CONFIG_SERIAL_8250_RUNTIME_UARTS=3 | ||||
| CONFIG_SERIAL_OF_PLATFORM=y | ||||
| # CONFIG_SG_POOL is not set | ||||
| CONFIG_SMP=y | ||||
| CONFIG_SMP_UP=y | ||||
| # CONFIG_SOC_MT7620 is not set | ||||
| CONFIG_SOC_MT7621=y | ||||
| # CONFIG_SOC_RT288X is not set | ||||
| # CONFIG_SOC_RT305X is not set | ||||
| # CONFIG_SOC_RT3883 is not set | ||||
| CONFIG_SPI=y | ||||
| CONFIG_SPI_MASTER=y | ||||
| CONFIG_SPI_MT7621=y | ||||
| # CONFIG_SPI_RT2880 is not set | ||||
| CONFIG_SRCU=y | ||||
| CONFIG_SWCONFIG=y | ||||
| CONFIG_SWPHY=y | ||||
| CONFIG_SYNC_R4K=y | ||||
| CONFIG_SYSCTL_EXCEPTION_TRACE=y | ||||
| CONFIG_SYS_HAS_CPU_MIPS32_R1=y | ||||
| CONFIG_SYS_HAS_CPU_MIPS32_R2=y | ||||
| CONFIG_SYS_HAS_EARLY_PRINTK=y | ||||
| CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y | ||||
| CONFIG_SYS_SUPPORTS_ARBIT_HZ=y | ||||
| CONFIG_SYS_SUPPORTS_HIGHMEM=y | ||||
| CONFIG_SYS_SUPPORTS_HOTPLUG_CPU=y | ||||
| CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y | ||||
| CONFIG_SYS_SUPPORTS_MIPS16=y | ||||
| CONFIG_SYS_SUPPORTS_MIPS_CPS=y | ||||
| CONFIG_SYS_SUPPORTS_MULTITHREADING=y | ||||
| CONFIG_SYS_SUPPORTS_SCHED_SMT=y | ||||
| CONFIG_SYS_SUPPORTS_SMP=y | ||||
| CONFIG_TICK_CPU_ACCOUNTING=y | ||||
| CONFIG_TREE_RCU=y | ||||
| CONFIG_UBIFS_FS=y | ||||
| CONFIG_UBIFS_FS_ADVANCED_COMPR=y | ||||
| CONFIG_UBIFS_FS_LZO=y | ||||
| CONFIG_UBIFS_FS_ZLIB=y | ||||
| CONFIG_USB_SUPPORT=y | ||||
| CONFIG_USE_OF=y | ||||
| CONFIG_WATCHDOG_CORE=y | ||||
| CONFIG_WEAK_ORDERING=y | ||||
| CONFIG_XPS=y | ||||
| CONFIG_ZLIB_DEFLATE=y | ||||
| CONFIG_ZLIB_INFLATE=y | ||||
| @@ -9,8 +9,6 @@ CPU_TYPE:=24kc | ||||
|  | ||||
| DEFAULT_PACKAGES += kmod-mt76 | ||||
|  | ||||
| KERNEL_PATCHVER:=4.4 | ||||
|  | ||||
| define Target/Description | ||||
| 	Build firmware images for Ralink MT7621 based boards. | ||||
| endef | ||||
|   | ||||
							
								
								
									
										210
									
								
								target/linux/ramips/mt7628/config-4.9
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								target/linux/ramips/mt7628/config-4.9
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,210 @@ | ||||
| CONFIG_ARCH_BINFMT_ELF_STATE=y | ||||
| CONFIG_ARCH_CLOCKSOURCE_DATA=y | ||||
| CONFIG_ARCH_DISCARD_MEMBLOCK=y | ||||
| CONFIG_ARCH_HAS_ELF_RANDOMIZE=y | ||||
| # CONFIG_ARCH_HAS_GCOV_PROFILE_ALL is not set | ||||
| CONFIG_ARCH_HAS_RESET_CONTROLLER=y | ||||
| # CONFIG_ARCH_HAS_SG_CHAIN is not set | ||||
| CONFIG_ARCH_HIBERNATION_POSSIBLE=y | ||||
| CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y | ||||
| CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y | ||||
| CONFIG_ARCH_SUPPORTS_UPROBES=y | ||||
| CONFIG_ARCH_SUSPEND_POSSIBLE=y | ||||
| CONFIG_ARCH_USE_BUILTIN_BSWAP=y | ||||
| CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y | ||||
| CONFIG_AT803X_PHY=y | ||||
| CONFIG_BLK_MQ_PCI=y | ||||
| CONFIG_CEVT_R4K=y | ||||
| CONFIG_CEVT_SYSTICK_QUIRK=y | ||||
| CONFIG_CLKDEV_LOOKUP=y | ||||
| CONFIG_CLKEVT_RT3352=y | ||||
| CONFIG_CLKSRC_MMIO=y | ||||
| CONFIG_CLKSRC_OF=y | ||||
| CONFIG_CLKSRC_PROBE=y | ||||
| CONFIG_CLONE_BACKWARDS=y | ||||
| CONFIG_CMDLINE="rootfstype=squashfs,jffs2" | ||||
| CONFIG_CMDLINE_BOOL=y | ||||
| # CONFIG_CMDLINE_OVERRIDE is not set | ||||
| CONFIG_CPU_GENERIC_DUMP_TLB=y | ||||
| CONFIG_CPU_HAS_PREFETCH=y | ||||
| CONFIG_CPU_HAS_RIXI=y | ||||
| CONFIG_CPU_HAS_SYNC=y | ||||
| CONFIG_CPU_LITTLE_ENDIAN=y | ||||
| CONFIG_CPU_MIPS32=y | ||||
| # CONFIG_CPU_MIPS32_R1 is not set | ||||
| CONFIG_CPU_MIPS32_R2=y | ||||
| CONFIG_CPU_MIPSR2=y | ||||
| CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y | ||||
| CONFIG_CPU_R4K_CACHE_TLB=y | ||||
| CONFIG_CPU_R4K_FPU=y | ||||
| CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y | ||||
| CONFIG_CPU_SUPPORTS_HIGHMEM=y | ||||
| CONFIG_CPU_SUPPORTS_MSA=y | ||||
| CONFIG_CRYPTO_RNG2=y | ||||
| CONFIG_CRYPTO_WORKQUEUE=y | ||||
| CONFIG_CSRC_R4K=y | ||||
| CONFIG_DEBUG_PINCTRL=y | ||||
| CONFIG_DMA_NONCOHERENT=y | ||||
| # CONFIG_DTB_MT7620A_EVAL is not set | ||||
| CONFIG_DTB_RT_NONE=y | ||||
| CONFIG_DTC=y | ||||
| CONFIG_EARLY_PRINTK=y | ||||
| CONFIG_FIXED_PHY=y | ||||
| CONFIG_GENERIC_ATOMIC64=y | ||||
| CONFIG_GENERIC_CLOCKEVENTS=y | ||||
| CONFIG_GENERIC_CMOS_UPDATE=y | ||||
| CONFIG_GENERIC_IO=y | ||||
| CONFIG_GENERIC_IRQ_CHIP=y | ||||
| CONFIG_GENERIC_IRQ_SHOW=y | ||||
| CONFIG_GENERIC_PCI_IOMAP=y | ||||
| CONFIG_GENERIC_PHY=y | ||||
| CONFIG_GENERIC_SCHED_CLOCK=y | ||||
| CONFIG_GENERIC_SMP_IDLE_THREAD=y | ||||
| CONFIG_GENERIC_TIME_VSYSCALL=y | ||||
| CONFIG_GPIOLIB=y | ||||
| CONFIG_GPIO_MT7621=y | ||||
| # CONFIG_GPIO_RALINK is not set | ||||
| CONFIG_GPIO_SYSFS=y | ||||
| CONFIG_HANDLE_DOMAIN_IRQ=y | ||||
| CONFIG_HARDWARE_WATCHPOINTS=y | ||||
| CONFIG_HAS_DMA=y | ||||
| CONFIG_HAS_IOMEM=y | ||||
| CONFIG_HAS_IOPORT_MAP=y | ||||
| # CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set | ||||
| # CONFIG_HAVE_ARCH_BITREVERSE is not set | ||||
| CONFIG_HAVE_ARCH_JUMP_LABEL=y | ||||
| CONFIG_HAVE_ARCH_KGDB=y | ||||
| CONFIG_HAVE_ARCH_SECCOMP_FILTER=y | ||||
| CONFIG_HAVE_ARCH_TRACEHOOK=y | ||||
| # CONFIG_HAVE_BOOTMEM_INFO_NODE is not set | ||||
| CONFIG_HAVE_CBPF_JIT=y | ||||
| CONFIG_HAVE_CC_STACKPROTECTOR=y | ||||
| CONFIG_HAVE_CLK=y | ||||
| CONFIG_HAVE_CONTEXT_TRACKING=y | ||||
| CONFIG_HAVE_C_RECORDMCOUNT=y | ||||
| CONFIG_HAVE_DEBUG_KMEMLEAK=y | ||||
| CONFIG_HAVE_DEBUG_STACKOVERFLOW=y | ||||
| CONFIG_HAVE_DMA_API_DEBUG=y | ||||
| CONFIG_HAVE_DMA_CONTIGUOUS=y | ||||
| CONFIG_HAVE_DYNAMIC_FTRACE=y | ||||
| CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y | ||||
| CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y | ||||
| CONFIG_HAVE_FUNCTION_TRACER=y | ||||
| CONFIG_HAVE_GENERIC_DMA_COHERENT=y | ||||
| CONFIG_HAVE_IDE=y | ||||
| CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y | ||||
| CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y | ||||
| CONFIG_HAVE_KVM=y | ||||
| CONFIG_HAVE_LATENCYTOP_SUPPORT=y | ||||
| CONFIG_HAVE_MEMBLOCK=y | ||||
| CONFIG_HAVE_MEMBLOCK_NODE_MAP=y | ||||
| CONFIG_HAVE_MOD_ARCH_SPECIFIC=y | ||||
| CONFIG_HAVE_NET_DSA=y | ||||
| CONFIG_HAVE_OPROFILE=y | ||||
| CONFIG_HAVE_PERF_EVENTS=y | ||||
| CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y | ||||
| CONFIG_HAVE_SYSCALL_TRACEPOINTS=y | ||||
| CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y | ||||
| CONFIG_HW_HAS_PCI=y | ||||
| CONFIG_HZ_PERIODIC=y | ||||
| CONFIG_ICPLUS_PHY=y | ||||
| CONFIG_INITRAMFS_SOURCE="" | ||||
| CONFIG_IRQCHIP=y | ||||
| CONFIG_IRQ_DOMAIN=y | ||||
| CONFIG_IRQ_FORCED_THREADING=y | ||||
| CONFIG_IRQ_INTC=y | ||||
| CONFIG_IRQ_MIPS_CPU=y | ||||
| CONFIG_IRQ_WORK=y | ||||
| CONFIG_LIBFDT=y | ||||
| CONFIG_MDIO_BOARDINFO=y | ||||
| CONFIG_MIPS=y | ||||
| CONFIG_MIPS_ASID_BITS=8 | ||||
| CONFIG_MIPS_ASID_SHIFT=0 | ||||
| CONFIG_MIPS_CLOCK_VSYSCALL=y | ||||
| # CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND is not set | ||||
| # CONFIG_MIPS_CMDLINE_DTB_EXTEND is not set | ||||
| # CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set | ||||
| CONFIG_MIPS_CMDLINE_FROM_DTB=y | ||||
| # CONFIG_MIPS_ELF_APPENDED_DTB is not set | ||||
| # CONFIG_MIPS_HUGE_TLB_SUPPORT is not set | ||||
| CONFIG_MIPS_L1_CACHE_SHIFT=5 | ||||
| # CONFIG_MIPS_MACHINE is not set | ||||
| CONFIG_MIPS_NO_APPENDED_DTB=y | ||||
| # CONFIG_MIPS_RAW_APPENDED_DTB is not set | ||||
| CONFIG_MIPS_SPRAM=y | ||||
| CONFIG_MODULES_USE_ELF_REL=y | ||||
| CONFIG_MT7621_WDT=y | ||||
| # CONFIG_MTD_CFI_INTELEXT is not set | ||||
| CONFIG_MTD_CMDLINE_PARTS=y | ||||
| CONFIG_MTD_M25P80=y | ||||
| CONFIG_MTD_PHYSMAP=y | ||||
| CONFIG_MTD_SPI_NOR=y | ||||
| CONFIG_MTD_SPLIT_FIRMWARE=y | ||||
| CONFIG_MTD_SPLIT_TRX_FW=y | ||||
| CONFIG_MTD_SPLIT_UIMAGE_FW=y | ||||
| CONFIG_NEED_DMA_MAP_STATE=y | ||||
| CONFIG_NEED_PER_CPU_KM=y | ||||
| CONFIG_NET_MEDIATEK_ESW_RT3050=y | ||||
| # CONFIG_NET_MEDIATEK_MT7620 is not set | ||||
| CONFIG_NET_MEDIATEK_RT3050=y | ||||
| CONFIG_NET_MEDIATEK_SOC=y | ||||
| CONFIG_NET_VENDOR_MEDIATEK=y | ||||
| CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y | ||||
| # CONFIG_NO_IOPORT_MAP is not set | ||||
| CONFIG_OF=y | ||||
| CONFIG_OF_ADDRESS=y | ||||
| CONFIG_OF_ADDRESS_PCI=y | ||||
| CONFIG_OF_EARLY_FLATTREE=y | ||||
| CONFIG_OF_FLATTREE=y | ||||
| CONFIG_OF_GPIO=y | ||||
| CONFIG_OF_IRQ=y | ||||
| CONFIG_OF_MDIO=y | ||||
| CONFIG_OF_NET=y | ||||
| CONFIG_OF_PCI=y | ||||
| CONFIG_OF_PCI_IRQ=y | ||||
| CONFIG_PCI=y | ||||
| CONFIG_PCI_DOMAINS=y | ||||
| CONFIG_PCI_DRIVERS_LEGACY=y | ||||
| CONFIG_PERF_USE_VMALLOC=y | ||||
| CONFIG_PGTABLE_LEVELS=2 | ||||
| CONFIG_PHYLIB=y | ||||
| CONFIG_PHY_RALINK_USB=y | ||||
| CONFIG_PINCTRL=y | ||||
| CONFIG_PINCTRL_RT2880=y | ||||
| # CONFIG_PINCTRL_SINGLE is not set | ||||
| CONFIG_RALINK=y | ||||
| # CONFIG_RALINK_WDT is not set | ||||
| # CONFIG_RCU_STALL_COMMON is not set | ||||
| CONFIG_RESET_CONTROLLER=y | ||||
| CONFIG_SCHED_HRTICK=y | ||||
| # CONFIG_SCHED_INFO is not set | ||||
| # CONFIG_SCSI_DMA is not set | ||||
| # CONFIG_SERIAL_8250_FSL is not set | ||||
| CONFIG_SERIAL_8250_NR_UARTS=3 | ||||
| CONFIG_SERIAL_8250_RUNTIME_UARTS=3 | ||||
| CONFIG_SERIAL_OF_PLATFORM=y | ||||
| # CONFIG_SG_POOL is not set | ||||
| CONFIG_SOC_MT7620=y | ||||
| # CONFIG_SOC_MT7621 is not set | ||||
| # CONFIG_SOC_RT288X is not set | ||||
| # CONFIG_SOC_RT305X is not set | ||||
| # CONFIG_SOC_RT3883 is not set | ||||
| CONFIG_SPI=y | ||||
| CONFIG_SPI_MASTER=y | ||||
| CONFIG_SPI_MT7621=y | ||||
| # CONFIG_SPI_RT2880 is not set | ||||
| CONFIG_SRCU=y | ||||
| CONFIG_SWCONFIG=y | ||||
| CONFIG_SWPHY=y | ||||
| CONFIG_SYSCTL_EXCEPTION_TRACE=y | ||||
| CONFIG_SYS_HAS_CPU_MIPS32_R1=y | ||||
| CONFIG_SYS_HAS_CPU_MIPS32_R2=y | ||||
| CONFIG_SYS_HAS_EARLY_PRINTK=y | ||||
| CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y | ||||
| CONFIG_SYS_SUPPORTS_ARBIT_HZ=y | ||||
| CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y | ||||
| CONFIG_SYS_SUPPORTS_MIPS16=y | ||||
| CONFIG_TICK_CPU_ACCOUNTING=y | ||||
| CONFIG_USB_SUPPORT=y | ||||
| CONFIG_USE_OF=y | ||||
| CONFIG_WATCHDOG_CORE=y | ||||
							
								
								
									
										213
									
								
								target/linux/ramips/mt7688/config-4.9
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										213
									
								
								target/linux/ramips/mt7688/config-4.9
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,213 @@ | ||||
| CONFIG_ARCH_BINFMT_ELF_STATE=y | ||||
| CONFIG_ARCH_CLOCKSOURCE_DATA=y | ||||
| CONFIG_ARCH_DISCARD_MEMBLOCK=y | ||||
| CONFIG_ARCH_HAS_ELF_RANDOMIZE=y | ||||
| # CONFIG_ARCH_HAS_GCOV_PROFILE_ALL is not set | ||||
| CONFIG_ARCH_HAS_RESET_CONTROLLER=y | ||||
| # CONFIG_ARCH_HAS_SG_CHAIN is not set | ||||
| CONFIG_ARCH_HIBERNATION_POSSIBLE=y | ||||
| CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y | ||||
| CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y | ||||
| CONFIG_ARCH_SUPPORTS_UPROBES=y | ||||
| CONFIG_ARCH_SUSPEND_POSSIBLE=y | ||||
| CONFIG_ARCH_USE_BUILTIN_BSWAP=y | ||||
| CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y | ||||
| CONFIG_AT803X_PHY=y | ||||
| CONFIG_BLK_MQ_PCI=y | ||||
| CONFIG_CEVT_R4K=y | ||||
| CONFIG_CEVT_SYSTICK_QUIRK=y | ||||
| CONFIG_CLKDEV_LOOKUP=y | ||||
| CONFIG_CLKEVT_RT3352=y | ||||
| CONFIG_CLKSRC_MMIO=y | ||||
| CONFIG_CLKSRC_OF=y | ||||
| CONFIG_CLKSRC_PROBE=y | ||||
| CONFIG_CLONE_BACKWARDS=y | ||||
| CONFIG_CMDLINE="rootfstype=squashfs,jffs2" | ||||
| CONFIG_CMDLINE_BOOL=y | ||||
| # CONFIG_CMDLINE_OVERRIDE is not set | ||||
| CONFIG_CPU_GENERIC_DUMP_TLB=y | ||||
| CONFIG_CPU_HAS_PREFETCH=y | ||||
| CONFIG_CPU_HAS_RIXI=y | ||||
| CONFIG_CPU_HAS_SYNC=y | ||||
| CONFIG_CPU_LITTLE_ENDIAN=y | ||||
| CONFIG_CPU_MIPS32=y | ||||
| # CONFIG_CPU_MIPS32_R1 is not set | ||||
| CONFIG_CPU_MIPS32_R2=y | ||||
| CONFIG_CPU_MIPSR2=y | ||||
| CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y | ||||
| CONFIG_CPU_R4K_CACHE_TLB=y | ||||
| CONFIG_CPU_R4K_FPU=y | ||||
| CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y | ||||
| CONFIG_CPU_SUPPORTS_HIGHMEM=y | ||||
| CONFIG_CPU_SUPPORTS_MSA=y | ||||
| CONFIG_CRYPTO_RNG2=y | ||||
| CONFIG_CRYPTO_WORKQUEUE=y | ||||
| CONFIG_CSRC_R4K=y | ||||
| CONFIG_DEBUG_PINCTRL=y | ||||
| CONFIG_DMA_NONCOHERENT=y | ||||
| # CONFIG_DTB_MT7620A_EVAL is not set | ||||
| CONFIG_DTB_RT_NONE=y | ||||
| CONFIG_DTC=y | ||||
| CONFIG_EARLY_PRINTK=y | ||||
| CONFIG_FIXED_PHY=y | ||||
| CONFIG_GENERIC_ATOMIC64=y | ||||
| CONFIG_GENERIC_CLOCKEVENTS=y | ||||
| CONFIG_GENERIC_CMOS_UPDATE=y | ||||
| CONFIG_GENERIC_IO=y | ||||
| CONFIG_GENERIC_IRQ_CHIP=y | ||||
| CONFIG_GENERIC_IRQ_SHOW=y | ||||
| CONFIG_GENERIC_PCI_IOMAP=y | ||||
| CONFIG_GENERIC_PHY=y | ||||
| CONFIG_GENERIC_SCHED_CLOCK=y | ||||
| CONFIG_GENERIC_SMP_IDLE_THREAD=y | ||||
| CONFIG_GENERIC_TIME_VSYSCALL=y | ||||
| CONFIG_GPIOLIB=y | ||||
| CONFIG_GPIO_MT7621=y | ||||
| # CONFIG_GPIO_RALINK is not set | ||||
| CONFIG_GPIO_SYSFS=y | ||||
| CONFIG_HANDLE_DOMAIN_IRQ=y | ||||
| CONFIG_HARDWARE_WATCHPOINTS=y | ||||
| CONFIG_HAS_DMA=y | ||||
| CONFIG_HAS_IOMEM=y | ||||
| CONFIG_HAS_IOPORT_MAP=y | ||||
| # CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set | ||||
| # CONFIG_HAVE_ARCH_BITREVERSE is not set | ||||
| CONFIG_HAVE_ARCH_JUMP_LABEL=y | ||||
| CONFIG_HAVE_ARCH_KGDB=y | ||||
| CONFIG_HAVE_ARCH_SECCOMP_FILTER=y | ||||
| CONFIG_HAVE_ARCH_TRACEHOOK=y | ||||
| # CONFIG_HAVE_BOOTMEM_INFO_NODE is not set | ||||
| CONFIG_HAVE_CBPF_JIT=y | ||||
| CONFIG_HAVE_CC_STACKPROTECTOR=y | ||||
| CONFIG_HAVE_CLK=y | ||||
| CONFIG_HAVE_CONTEXT_TRACKING=y | ||||
| CONFIG_HAVE_C_RECORDMCOUNT=y | ||||
| CONFIG_HAVE_DEBUG_KMEMLEAK=y | ||||
| CONFIG_HAVE_DEBUG_STACKOVERFLOW=y | ||||
| CONFIG_HAVE_DMA_API_DEBUG=y | ||||
| CONFIG_HAVE_DMA_CONTIGUOUS=y | ||||
| CONFIG_HAVE_DYNAMIC_FTRACE=y | ||||
| CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y | ||||
| CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y | ||||
| CONFIG_HAVE_FUNCTION_TRACER=y | ||||
| CONFIG_HAVE_GENERIC_DMA_COHERENT=y | ||||
| CONFIG_HAVE_IDE=y | ||||
| CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y | ||||
| CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y | ||||
| CONFIG_HAVE_KVM=y | ||||
| CONFIG_HAVE_LATENCYTOP_SUPPORT=y | ||||
| CONFIG_HAVE_MEMBLOCK=y | ||||
| CONFIG_HAVE_MEMBLOCK_NODE_MAP=y | ||||
| CONFIG_HAVE_MOD_ARCH_SPECIFIC=y | ||||
| CONFIG_HAVE_NET_DSA=y | ||||
| CONFIG_HAVE_OPROFILE=y | ||||
| CONFIG_HAVE_PERF_EVENTS=y | ||||
| CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y | ||||
| CONFIG_HAVE_SYSCALL_TRACEPOINTS=y | ||||
| CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y | ||||
| CONFIG_HW_HAS_PCI=y | ||||
| CONFIG_HZ_PERIODIC=y | ||||
| CONFIG_ICPLUS_PHY=y | ||||
| CONFIG_INITRAMFS_SOURCE="" | ||||
| CONFIG_IRQCHIP=y | ||||
| CONFIG_IRQ_DOMAIN=y | ||||
| CONFIG_IRQ_FORCED_THREADING=y | ||||
| CONFIG_IRQ_INTC=y | ||||
| CONFIG_IRQ_MIPS_CPU=y | ||||
| CONFIG_IRQ_WORK=y | ||||
| CONFIG_LIBFDT=y | ||||
| CONFIG_MDIO_BOARDINFO=y | ||||
| CONFIG_MIPS=y | ||||
| CONFIG_MIPS_ASID_BITS=8 | ||||
| CONFIG_MIPS_ASID_SHIFT=0 | ||||
| CONFIG_MIPS_CLOCK_VSYSCALL=y | ||||
| # CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND is not set | ||||
| # CONFIG_MIPS_CMDLINE_DTB_EXTEND is not set | ||||
| # CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set | ||||
| CONFIG_MIPS_CMDLINE_FROM_DTB=y | ||||
| # CONFIG_MIPS_ELF_APPENDED_DTB is not set | ||||
| CONFIG_MIPS_FPU_EMULATOR=y | ||||
| # CONFIG_MIPS_HUGE_TLB_SUPPORT is not set | ||||
| CONFIG_MIPS_L1_CACHE_SHIFT=5 | ||||
| # CONFIG_MIPS_MACHINE is not set | ||||
| CONFIG_MIPS_NO_APPENDED_DTB=y | ||||
| # CONFIG_MIPS_RAW_APPENDED_DTB is not set | ||||
| CONFIG_MIPS_SPRAM=y | ||||
| CONFIG_MODULES_USE_ELF_REL=y | ||||
| CONFIG_MT7621_WDT=y | ||||
| # CONFIG_MTD_CFI_INTELEXT is not set | ||||
| CONFIG_MTD_CMDLINE_PARTS=y | ||||
| CONFIG_MTD_M25P80=y | ||||
| CONFIG_MTD_PHYSMAP=y | ||||
| CONFIG_MTD_SPI_NOR=y | ||||
| CONFIG_MTD_SPLIT_FIRMWARE=y | ||||
| CONFIG_MTD_SPLIT_UIMAGE_FW=y | ||||
| CONFIG_NEED_DMA_MAP_STATE=y | ||||
| CONFIG_NEED_PER_CPU_KM=y | ||||
| CONFIG_NET_MEDIATEK_ESW_RT3050=y | ||||
| # CONFIG_NET_MEDIATEK_MT7620 is not set | ||||
| CONFIG_NET_MEDIATEK_RT3050=y | ||||
| CONFIG_NET_MEDIATEK_SOC=y | ||||
| CONFIG_NET_VENDOR_MEDIATEK=y | ||||
| CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y | ||||
| # CONFIG_NO_IOPORT_MAP is not set | ||||
| CONFIG_OF=y | ||||
| CONFIG_OF_ADDRESS=y | ||||
| CONFIG_OF_ADDRESS_PCI=y | ||||
| CONFIG_OF_EARLY_FLATTREE=y | ||||
| CONFIG_OF_FLATTREE=y | ||||
| CONFIG_OF_GPIO=y | ||||
| CONFIG_OF_IRQ=y | ||||
| CONFIG_OF_MDIO=y | ||||
| CONFIG_OF_NET=y | ||||
| CONFIG_OF_PCI=y | ||||
| CONFIG_OF_PCI_IRQ=y | ||||
| CONFIG_PCI=y | ||||
| CONFIG_PCI_DOMAINS=y | ||||
| CONFIG_PCI_DRIVERS_LEGACY=y | ||||
| CONFIG_PERF_USE_VMALLOC=y | ||||
| CONFIG_PGTABLE_LEVELS=2 | ||||
| CONFIG_PHYLIB=y | ||||
| CONFIG_PHY_RALINK_USB=y | ||||
| CONFIG_PINCTRL=y | ||||
| CONFIG_PINCTRL_RT2880=y | ||||
| # CONFIG_PINCTRL_SINGLE is not set | ||||
| CONFIG_PWM=y | ||||
| CONFIG_PWM_MEDIATEK=y | ||||
| CONFIG_PWM_SYSFS=y | ||||
| CONFIG_RALINK=y | ||||
| # CONFIG_RALINK_WDT is not set | ||||
| # CONFIG_RCU_STALL_COMMON is not set | ||||
| CONFIG_RESET_CONTROLLER=y | ||||
| CONFIG_SCHED_HRTICK=y | ||||
| # CONFIG_SCHED_INFO is not set | ||||
| # CONFIG_SCSI_DMA is not set | ||||
| # CONFIG_SERIAL_8250_FSL is not set | ||||
| CONFIG_SERIAL_8250_NR_UARTS=4 | ||||
| CONFIG_SERIAL_8250_RUNTIME_UARTS=4 | ||||
| CONFIG_SERIAL_OF_PLATFORM=y | ||||
| # CONFIG_SG_POOL is not set | ||||
| CONFIG_SOC_MT7620=y | ||||
| # CONFIG_SOC_MT7621 is not set | ||||
| # CONFIG_SOC_RT288X is not set | ||||
| # CONFIG_SOC_RT305X is not set | ||||
| # CONFIG_SOC_RT3883 is not set | ||||
| CONFIG_SPI=y | ||||
| CONFIG_SPI_MASTER=y | ||||
| CONFIG_SPI_MT7621=y | ||||
| # CONFIG_SPI_RT2880 is not set | ||||
| CONFIG_SRCU=y | ||||
| CONFIG_SWCONFIG=y | ||||
| CONFIG_SWPHY=y | ||||
| CONFIG_SYSCTL_EXCEPTION_TRACE=y | ||||
| CONFIG_SYS_HAS_CPU_MIPS32_R1=y | ||||
| CONFIG_SYS_HAS_CPU_MIPS32_R2=y | ||||
| CONFIG_SYS_HAS_EARLY_PRINTK=y | ||||
| CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y | ||||
| CONFIG_SYS_SUPPORTS_ARBIT_HZ=y | ||||
| CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y | ||||
| CONFIG_SYS_SUPPORTS_MIPS16=y | ||||
| CONFIG_TICK_CPU_ACCOUNTING=y | ||||
| CONFIG_USB_SUPPORT=y | ||||
| CONFIG_USE_OF=y | ||||
| CONFIG_WATCHDOG_CORE=y | ||||
| @@ -0,0 +1,857 @@ | ||||
| From fec11d4e8dc5cc79bcd7c8fd55038ac21ac39965 Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <blogic@openwrt.org> | ||||
| Date: Sun, 16 Mar 2014 05:22:39 +0000 | ||||
| Subject: [PATCH 04/53] MIPS: ralink: add MT7621 pcie driver | ||||
|  | ||||
| Signed-off-by: John Crispin <blogic@openwrt.org> | ||||
| --- | ||||
|  arch/mips/pci/Makefile     |    1 + | ||||
|  arch/mips/pci/pci-mt7621.c |  813 ++++++++++++++++++++++++++++++++++++++++++++ | ||||
|  2 files changed, 814 insertions(+) | ||||
|  create mode 100644 arch/mips/pci/pci-mt7621.c | ||||
|  | ||||
| --- a/arch/mips/pci/Makefile | ||||
| +++ b/arch/mips/pci/Makefile | ||||
| @@ -46,6 +46,7 @@ obj-$(CONFIG_SNI_RM)		+= fixup-sni.o ops | ||||
|  obj-$(CONFIG_LANTIQ)		+= fixup-lantiq.o | ||||
|  obj-$(CONFIG_PCI_LANTIQ)	+= pci-lantiq.o ops-lantiq.o | ||||
|  obj-$(CONFIG_SOC_MT7620)	+= pci-mt7620.o | ||||
| +obj-$(CONFIG_SOC_MT7621)	+= pci-mt7621.o | ||||
|  obj-$(CONFIG_SOC_RT288X)	+= pci-rt2880.o | ||||
|  obj-$(CONFIG_SOC_RT3883)	+= pci-rt3883.o | ||||
|  obj-$(CONFIG_TANBAC_TB0219)	+= fixup-tb0219.o | ||||
| --- /dev/null | ||||
| +++ b/arch/mips/pci/pci-mt7621.c | ||||
| @@ -0,0 +1,832 @@ | ||||
| +/************************************************************************** | ||||
| + * | ||||
| + *  BRIEF MODULE DESCRIPTION | ||||
| + *     PCI init for Ralink RT2880 solution | ||||
| + * | ||||
| + *  Copyright 2007 Ralink Inc. (bruce_chang@ralinktech.com.tw) | ||||
| + * | ||||
| + *  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. | ||||
| + * | ||||
| + * | ||||
| + ************************************************************************** | ||||
| + * May 2007 Bruce Chang | ||||
| + * Initial Release | ||||
| + * | ||||
| + * May 2009 Bruce Chang | ||||
| + * support RT2880/RT3883 PCIe | ||||
| + * | ||||
| + * May 2011 Bruce Chang | ||||
| + * support RT6855/MT7620 PCIe | ||||
| + * | ||||
| + ************************************************************************** | ||||
| + */ | ||||
| + | ||||
| +#include <linux/types.h> | ||||
| +#include <linux/pci.h> | ||||
| +#include <linux/kernel.h> | ||||
| +#include <linux/slab.h> | ||||
| +#include <linux/version.h> | ||||
| +#include <asm/pci.h> | ||||
| +#include <asm/io.h> | ||||
| +#include <asm/mips-cm.h> | ||||
| +#include <linux/init.h> | ||||
| +#include <linux/module.h> | ||||
| +#include <linux/delay.h> | ||||
| +#include <linux/of.h> | ||||
| +#include <linux/of_pci.h> | ||||
| +#include <linux/platform_device.h> | ||||
| + | ||||
| +#include <ralink_regs.h> | ||||
| + | ||||
| +extern void pcie_phy_init(void); | ||||
| +extern void chk_phy_pll(void); | ||||
| + | ||||
| +/* | ||||
| + * These functions and structures provide the BIOS scan and mapping of the PCI | ||||
| + * devices. | ||||
| + */ | ||||
| + | ||||
| +#define CONFIG_PCIE_PORT0 | ||||
| +#define CONFIG_PCIE_PORT1 | ||||
| +#define CONFIG_PCIE_PORT2 | ||||
| +#define RALINK_PCIE0_CLK_EN             (1<<24) | ||||
| +#define RALINK_PCIE1_CLK_EN             (1<<25) | ||||
| +#define RALINK_PCIE2_CLK_EN             (1<<26) | ||||
| + | ||||
| +#define RALINK_PCI_CONFIG_ADDR                         0x20 | ||||
| +#define RALINK_PCI_CONFIG_DATA_VIRTUAL_REG     0x24 | ||||
| +#define SURFBOARDINT_PCIE0       11      /* PCIE0 */ | ||||
| +#define RALINK_INT_PCIE0         SURFBOARDINT_PCIE0 | ||||
| +#define RALINK_INT_PCIE1         SURFBOARDINT_PCIE1 | ||||
| +#define RALINK_INT_PCIE2         SURFBOARDINT_PCIE2 | ||||
| +#define SURFBOARDINT_PCIE1       31     /* PCIE1 */ | ||||
| +#define SURFBOARDINT_PCIE2       32     /* PCIE2 */ | ||||
| +#define RALINK_PCI_MEMBASE              *(volatile u32 *)(RALINK_PCI_BASE + 0x0028) | ||||
| +#define RALINK_PCI_IOBASE               *(volatile u32 *)(RALINK_PCI_BASE + 0x002C) | ||||
| +#define RALINK_PCIE0_RST                (1<<24) | ||||
| +#define RALINK_PCIE1_RST                (1<<25) | ||||
| +#define RALINK_PCIE2_RST                (1<<26) | ||||
| +#define RALINK_SYSCTL_BASE              0xBE000000 | ||||
| + | ||||
| +#define RALINK_PCI_PCICFG_ADDR          *(volatile u32 *)(RALINK_PCI_BASE + 0x0000) | ||||
| +#define RALINK_PCI_PCIMSK_ADDR          *(volatile u32 *)(RALINK_PCI_BASE + 0x000C) | ||||
| +#define RALINK_PCI_BASE                 0xBE140000 | ||||
| + | ||||
| +#define RALINK_PCIEPHY_P0P1_CTL_OFFSET (RALINK_PCI_BASE + 0x9000) | ||||
| +#define RT6855_PCIE0_OFFSET     0x2000 | ||||
| +#define RT6855_PCIE1_OFFSET     0x3000 | ||||
| +#define RT6855_PCIE2_OFFSET     0x4000 | ||||
| + | ||||
| +#define RALINK_PCI0_BAR0SETUP_ADDR      *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0010) | ||||
| +#define RALINK_PCI0_IMBASEBAR0_ADDR     *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0018) | ||||
| +#define RALINK_PCI0_ID                  *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0030) | ||||
| +#define RALINK_PCI0_CLASS               *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0034) | ||||
| +#define RALINK_PCI0_SUBID               *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0038) | ||||
| +#define RALINK_PCI0_STATUS              *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0050) | ||||
| +#define RALINK_PCI0_DERR                *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0060) | ||||
| +#define RALINK_PCI0_ECRC                *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE0_OFFSET + 0x0064) | ||||
| + | ||||
| +#define RALINK_PCI1_BAR0SETUP_ADDR      *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0010) | ||||
| +#define RALINK_PCI1_IMBASEBAR0_ADDR     *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0018) | ||||
| +#define RALINK_PCI1_ID                  *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0030) | ||||
| +#define RALINK_PCI1_CLASS               *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0034) | ||||
| +#define RALINK_PCI1_SUBID               *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0038) | ||||
| +#define RALINK_PCI1_STATUS              *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0050) | ||||
| +#define RALINK_PCI1_DERR                *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0060) | ||||
| +#define RALINK_PCI1_ECRC                *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE1_OFFSET + 0x0064) | ||||
| + | ||||
| +#define RALINK_PCI2_BAR0SETUP_ADDR      *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0010) | ||||
| +#define RALINK_PCI2_IMBASEBAR0_ADDR     *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0018) | ||||
| +#define RALINK_PCI2_ID                  *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0030) | ||||
| +#define RALINK_PCI2_CLASS               *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0034) | ||||
| +#define RALINK_PCI2_SUBID               *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0038) | ||||
| +#define RALINK_PCI2_STATUS              *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0050) | ||||
| +#define RALINK_PCI2_DERR                *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0060) | ||||
| +#define RALINK_PCI2_ECRC                *(volatile u32 *)(RALINK_PCI_BASE + RT6855_PCIE2_OFFSET + 0x0064) | ||||
| + | ||||
| +#define RALINK_PCIEPHY_P0P1_CTL_OFFSET  (RALINK_PCI_BASE + 0x9000) | ||||
| +#define RALINK_PCIEPHY_P2_CTL_OFFSET    (RALINK_PCI_BASE + 0xA000) | ||||
| + | ||||
| + | ||||
| +#define MV_WRITE(ofs, data)  \ | ||||
| +        *(volatile u32 *)(RALINK_PCI_BASE+(ofs)) = cpu_to_le32(data) | ||||
| +#define MV_READ(ofs, data)   \ | ||||
| +	        *(data) = le32_to_cpu(*(volatile u32 *)(RALINK_PCI_BASE+(ofs))) | ||||
| +#define MV_READ_DATA(ofs)    \ | ||||
| +		        le32_to_cpu(*(volatile u32 *)(RALINK_PCI_BASE+(ofs))) | ||||
| + | ||||
| +#define MV_WRITE_16(ofs, data)  \ | ||||
| +        *(volatile u16 *)(RALINK_PCI_BASE+(ofs)) = cpu_to_le16(data) | ||||
| +#define MV_READ_16(ofs, data)   \ | ||||
| +	        *(data) = le16_to_cpu(*(volatile u16 *)(RALINK_PCI_BASE+(ofs))) | ||||
| + | ||||
| +#define MV_WRITE_8(ofs, data)  \ | ||||
| +        *(volatile u8 *)(RALINK_PCI_BASE+(ofs)) = data | ||||
| +#define MV_READ_8(ofs, data)   \ | ||||
| +	        *(data) = *(volatile u8 *)(RALINK_PCI_BASE+(ofs)) | ||||
| + | ||||
| + | ||||
| + | ||||
| +#define RALINK_PCI_MM_MAP_BASE	0x60000000 | ||||
| +#define RALINK_PCI_IO_MAP_BASE	0x1e160000 | ||||
| + | ||||
| +#define RALINK_SYSTEM_CONTROL_BASE	0xbe000000 | ||||
| +#define GPIO_PERST | ||||
| +#define ASSERT_SYSRST_PCIE(val)		do {	\ | ||||
| +						if (*(unsigned int *)(0xbe00000c) == 0x00030101)	\ | ||||
| +							RALINK_RSTCTRL |= val;	\ | ||||
| +						else	\ | ||||
| +							RALINK_RSTCTRL &= ~val;	\ | ||||
| +					} while(0) | ||||
| +#define DEASSERT_SYSRST_PCIE(val) 	do {	\ | ||||
| +						if (*(unsigned int *)(0xbe00000c) == 0x00030101)	\ | ||||
| +							RALINK_RSTCTRL &= ~val;	\ | ||||
| +						else	\ | ||||
| +							RALINK_RSTCTRL |= val;	\ | ||||
| +					} while(0) | ||||
| +#define RALINK_SYSCFG1			*(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x14) | ||||
| +#define RALINK_CLKCFG1			*(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x30) | ||||
| +#define RALINK_RSTCTRL			*(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x34) | ||||
| +#define RALINK_GPIOMODE			*(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x60) | ||||
| +#define RALINK_PCIE_CLK_GEN		*(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x7c) | ||||
| +#define RALINK_PCIE_CLK_GEN1		*(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x80) | ||||
| +#define PPLL_CFG1			*(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0x9c) | ||||
| +#define PPLL_DRV			*(unsigned int *)(RALINK_SYSTEM_CONTROL_BASE + 0xa0) | ||||
| +//RALINK_SYSCFG1 bit | ||||
| +#define RALINK_PCI_HOST_MODE_EN		(1<<7) | ||||
| +#define RALINK_PCIE_RC_MODE_EN		(1<<8) | ||||
| +//RALINK_RSTCTRL bit | ||||
| +#define RALINK_PCIE_RST			(1<<23) | ||||
| +#define RALINK_PCI_RST			(1<<24) | ||||
| +//RALINK_CLKCFG1 bit | ||||
| +#define RALINK_PCI_CLK_EN		(1<<19) | ||||
| +#define RALINK_PCIE_CLK_EN		(1<<21) | ||||
| +//RALINK_GPIOMODE bit | ||||
| +#define PCI_SLOTx2			(1<<11) | ||||
| +#define PCI_SLOTx1			(2<<11) | ||||
| +//MTK PCIE PLL bit | ||||
| +#define PDRV_SW_SET			(1<<31) | ||||
| +#define LC_CKDRVPD_			(1<<19) | ||||
| + | ||||
| +#define MEMORY_BASE 0x0 | ||||
| +static int pcie_link_status = 0; | ||||
| + | ||||
| +#define PCI_ACCESS_READ_1  0 | ||||
| +#define PCI_ACCESS_READ_2  1 | ||||
| +#define PCI_ACCESS_READ_4  2 | ||||
| +#define PCI_ACCESS_WRITE_1 3 | ||||
| +#define PCI_ACCESS_WRITE_2 4 | ||||
| +#define PCI_ACCESS_WRITE_4 5 | ||||
| + | ||||
| +static int config_access(unsigned char access_type, struct pci_bus *bus, | ||||
| +			unsigned int devfn, unsigned int where, u32 * data) | ||||
| +{ | ||||
| +	unsigned int slot = PCI_SLOT(devfn); | ||||
| +	u8 func = PCI_FUNC(devfn); | ||||
| +	uint32_t address_reg, data_reg; | ||||
| +	unsigned int address; | ||||
| + | ||||
| +	address_reg = RALINK_PCI_CONFIG_ADDR; | ||||
| +	data_reg = RALINK_PCI_CONFIG_DATA_VIRTUAL_REG; | ||||
| + | ||||
| +	address = (((where&0xF00)>>8)<<24) |(bus->number << 16) | (slot << 11) | (func << 8) | (where & 0xfc) | 0x80000000; | ||||
| +	MV_WRITE(address_reg, address); | ||||
| + | ||||
| +	switch(access_type) { | ||||
| +	case PCI_ACCESS_WRITE_1: | ||||
| +		MV_WRITE_8(data_reg+(where&0x3), *data); | ||||
| +		break; | ||||
| +	case PCI_ACCESS_WRITE_2: | ||||
| +		MV_WRITE_16(data_reg+(where&0x3), *data); | ||||
| +		break; | ||||
| +	case PCI_ACCESS_WRITE_4: | ||||
| +		MV_WRITE(data_reg, *data); | ||||
| +		break; | ||||
| +	case PCI_ACCESS_READ_1: | ||||
| +		MV_READ_8( data_reg+(where&0x3), data); | ||||
| +		break; | ||||
| +	case PCI_ACCESS_READ_2: | ||||
| +		MV_READ_16(data_reg+(where&0x3), data); | ||||
| +		break; | ||||
| +	case PCI_ACCESS_READ_4: | ||||
| +		MV_READ(data_reg, data); | ||||
| +		break; | ||||
| +	default: | ||||
| +		printk("no specify access type\n"); | ||||
| +		break; | ||||
| +	} | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static int | ||||
| +read_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 * val) | ||||
| +{ | ||||
| +	return config_access(PCI_ACCESS_READ_1, bus, devfn, (unsigned int)where, (u32 *)val); | ||||
| +} | ||||
| + | ||||
| +static int | ||||
| +read_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 * val) | ||||
| +{ | ||||
| +	return config_access(PCI_ACCESS_READ_2, bus, devfn, (unsigned int)where, (u32 *)val); | ||||
| +} | ||||
| + | ||||
| +static int | ||||
| +read_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 * val) | ||||
| +{ | ||||
| +	return config_access(PCI_ACCESS_READ_4, bus, devfn, (unsigned int)where, (u32 *)val); | ||||
| +} | ||||
| + | ||||
| +static int | ||||
| +write_config_byte(struct pci_bus *bus, unsigned int devfn, int where, u8 val) | ||||
| +{ | ||||
| +	if (config_access(PCI_ACCESS_WRITE_1, bus, devfn, (unsigned int)where, (u32 *)&val)) | ||||
| +		return -1; | ||||
| + | ||||
| +	return PCIBIOS_SUCCESSFUL; | ||||
| +} | ||||
| + | ||||
| +static int | ||||
| +write_config_word(struct pci_bus *bus, unsigned int devfn, int where, u16 val) | ||||
| +{ | ||||
| +	if (config_access(PCI_ACCESS_WRITE_2, bus, devfn, where, (u32 *)&val)) | ||||
| +		return -1; | ||||
| + | ||||
| +	return PCIBIOS_SUCCESSFUL; | ||||
| +} | ||||
| + | ||||
| +static int | ||||
| +write_config_dword(struct pci_bus *bus, unsigned int devfn, int where, u32 val) | ||||
| +{ | ||||
| +	if (config_access(PCI_ACCESS_WRITE_4, bus, devfn, where, &val)) | ||||
| +		return -1; | ||||
| + | ||||
| +	return PCIBIOS_SUCCESSFUL; | ||||
| +} | ||||
| + | ||||
| + | ||||
| +static int | ||||
| +pci_config_read(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 * val) | ||||
| +{ | ||||
| +	switch (size) { | ||||
| +	case 1: | ||||
| +		return read_config_byte(bus, devfn, where, (u8 *) val); | ||||
| +	case 2: | ||||
| +		return read_config_word(bus, devfn, where, (u16 *) val); | ||||
| +	default: | ||||
| +		return read_config_dword(bus, devfn, where, val); | ||||
| +	} | ||||
| +} | ||||
| + | ||||
| +static int | ||||
| +pci_config_write(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val) | ||||
| +{ | ||||
| +	switch (size) { | ||||
| +	case 1: | ||||
| +		return write_config_byte(bus, devfn, where, (u8) val); | ||||
| +	case 2: | ||||
| +		return write_config_word(bus, devfn, where, (u16) val); | ||||
| +	default: | ||||
| +		return write_config_dword(bus, devfn, where, val); | ||||
| +	} | ||||
| +} | ||||
| + | ||||
| +struct pci_ops mt7621_pci_ops= { | ||||
| +	.read		=  pci_config_read, | ||||
| +	.write		= pci_config_write, | ||||
| +}; | ||||
| + | ||||
| +static struct resource mt7621_res_pci_mem1 = { | ||||
| +	.name		= "PCI MEM1", | ||||
| +	.start		= RALINK_PCI_MM_MAP_BASE, | ||||
| +	.end		= (u32)((RALINK_PCI_MM_MAP_BASE + (unsigned char *)0x0fffffff)), | ||||
| +	.flags		= IORESOURCE_MEM, | ||||
| +}; | ||||
| +static struct resource mt7621_res_pci_io1 = { | ||||
| +	.name		= "PCI I/O1", | ||||
| +	.start		= RALINK_PCI_IO_MAP_BASE, | ||||
| +	.end		= (u32)((RALINK_PCI_IO_MAP_BASE + (unsigned char *)0x0ffff)), | ||||
| +	.flags		= IORESOURCE_IO, | ||||
| +}; | ||||
| + | ||||
| +static struct pci_controller mt7621_controller = { | ||||
| +	.pci_ops	= &mt7621_pci_ops, | ||||
| +	.mem_resource	= &mt7621_res_pci_mem1, | ||||
| +	.io_resource	= &mt7621_res_pci_io1, | ||||
| +	.mem_offset	= 0x00000000UL, | ||||
| +	.io_offset	= 0x00000000UL, | ||||
| +	.io_map_base	= 0xa0000000, | ||||
| +}; | ||||
| + | ||||
| +static void | ||||
| +read_config(unsigned long bus, unsigned long dev, unsigned long func, unsigned long reg, unsigned long *val) | ||||
| +{ | ||||
| +	unsigned int address_reg, data_reg, address; | ||||
| + | ||||
| +	address_reg = RALINK_PCI_CONFIG_ADDR; | ||||
| +        data_reg = RALINK_PCI_CONFIG_DATA_VIRTUAL_REG; | ||||
| +	address = (((reg & 0xF00)>>8)<<24) | (bus << 16) | (dev << 11) | (func << 8) | (reg & 0xfc) | 0x80000000 ; | ||||
| +        MV_WRITE(address_reg, address); | ||||
| +        MV_READ(data_reg, val); | ||||
| +	return; | ||||
| +} | ||||
| + | ||||
| +static void | ||||
| +write_config(unsigned long bus, unsigned long dev, unsigned long func, unsigned long reg, unsigned long val) | ||||
| +{ | ||||
| +	unsigned int address_reg, data_reg, address; | ||||
| + | ||||
| +	address_reg = RALINK_PCI_CONFIG_ADDR; | ||||
| +	data_reg = RALINK_PCI_CONFIG_DATA_VIRTUAL_REG; | ||||
| +	address = (((reg & 0xF00)>>8)<<24) | (bus << 16) | (dev << 11) | (func << 8) | (reg & 0xfc) | 0x80000000 ; | ||||
| +	MV_WRITE(address_reg, address); | ||||
| +	MV_WRITE(data_reg, val); | ||||
| +	return; | ||||
| +} | ||||
| + | ||||
| + | ||||
| +int __init | ||||
| +pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) | ||||
| +{ | ||||
| +	u16 cmd; | ||||
| +	u32 val; | ||||
| +	int irq = 0; | ||||
| + | ||||
| +	if ((dev->bus->number == 0) && (slot == 0)) { | ||||
| +		write_config(0, 0, 0, PCI_BASE_ADDRESS_0, MEMORY_BASE); | ||||
| +		read_config(0, 0, 0, PCI_BASE_ADDRESS_0, (unsigned long *)&val); | ||||
| +		printk("BAR0 at slot 0 = %x\n", val); | ||||
| +		printk("bus=0x%x, slot = 0x%x\n",dev->bus->number, slot); | ||||
| +	} else if((dev->bus->number == 0) && (slot == 0x1)) { | ||||
| +		write_config(0, 1, 0, PCI_BASE_ADDRESS_0, MEMORY_BASE); | ||||
| +		read_config(0, 1, 0, PCI_BASE_ADDRESS_0, (unsigned long *)&val); | ||||
| +		printk("BAR0 at slot 1 = %x\n", val); | ||||
| +		printk("bus=0x%x, slot = 0x%x\n",dev->bus->number, slot); | ||||
| +	} else if((dev->bus->number == 0) && (slot == 0x2)) { | ||||
| +		write_config(0, 2, 0, PCI_BASE_ADDRESS_0, MEMORY_BASE); | ||||
| +		read_config(0, 2, 0, PCI_BASE_ADDRESS_0, (unsigned long *)&val); | ||||
| +		printk("BAR0 at slot 2 = %x\n", val); | ||||
| +		printk("bus=0x%x, slot = 0x%x\n",dev->bus->number, slot); | ||||
| +	} else if ((dev->bus->number == 1) && (slot == 0x0)) { | ||||
| +		switch (pcie_link_status) { | ||||
| +		case 2: | ||||
| +		case 6: | ||||
| +			irq = RALINK_INT_PCIE1; | ||||
| +			break; | ||||
| +		case 4: | ||||
| +			irq = RALINK_INT_PCIE2; | ||||
| +			break; | ||||
| +		default: | ||||
| +			irq = RALINK_INT_PCIE0; | ||||
| +		} | ||||
| +		printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq); | ||||
| +	} else if ((dev->bus->number == 2) && (slot == 0x0)) { | ||||
| +		switch (pcie_link_status) { | ||||
| +		case 5: | ||||
| +		case 6: | ||||
| +			irq = RALINK_INT_PCIE2; | ||||
| +			break; | ||||
| +		default: | ||||
| +			irq = RALINK_INT_PCIE1; | ||||
| +		} | ||||
| +		printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq); | ||||
| +	} else if ((dev->bus->number == 2) && (slot == 0x1)) { | ||||
| +		switch (pcie_link_status) { | ||||
| +		case 5: | ||||
| +		case 6: | ||||
| +			irq = RALINK_INT_PCIE2; | ||||
| +			break; | ||||
| +		default: | ||||
| +			irq = RALINK_INT_PCIE1; | ||||
| +		} | ||||
| +		printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq); | ||||
| +	} else if ((dev->bus->number ==3) && (slot == 0x0)) { | ||||
| +		irq = RALINK_INT_PCIE2; | ||||
| +		printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq); | ||||
| +	} else if ((dev->bus->number ==3) && (slot == 0x1)) { | ||||
| +		irq = RALINK_INT_PCIE2; | ||||
| +		printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq); | ||||
| +	} else if ((dev->bus->number ==3) && (slot == 0x2)) { | ||||
| +		irq = RALINK_INT_PCIE2; | ||||
| +		printk("bus=0x%x, slot = 0x%x, irq=0x%x\n",dev->bus->number, slot, dev->irq); | ||||
| +	} else { | ||||
| +		printk("bus=0x%x, slot = 0x%x\n",dev->bus->number, slot); | ||||
| +		return 0; | ||||
| +	} | ||||
| + | ||||
| +	pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE, 0x14);  //configure cache line size 0x14 | ||||
| +	pci_write_config_byte(dev, PCI_LATENCY_TIMER, 0xFF);  //configure latency timer 0x10 | ||||
| +	pci_read_config_word(dev, PCI_COMMAND, &cmd); | ||||
| +	cmd = cmd | PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEMORY; | ||||
| +	pci_write_config_word(dev, PCI_COMMAND, cmd); | ||||
| +	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq); | ||||
| +	return irq; | ||||
| +} | ||||
| + | ||||
| +void | ||||
| +set_pcie_phy(u32 *addr, int start_b, int bits, int val) | ||||
| +{ | ||||
| +//	printk("0x%p:", addr); | ||||
| +//	printk(" %x", *addr); | ||||
| +	*(unsigned int *)(addr) &= ~(((1<<bits) - 1)<<start_b); | ||||
| +	*(unsigned int *)(addr) |= val << start_b; | ||||
| +//	printk(" -> %x\n", *addr); | ||||
| +} | ||||
| + | ||||
| +void | ||||
| +bypass_pipe_rst(void) | ||||
| +{ | ||||
| +#if defined (CONFIG_PCIE_PORT0) | ||||
| +	/* PCIe Port 0 */ | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x02c), 12, 1, 0x01);	// rg_pe1_pipe_rst_b | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x02c),  4, 1, 0x01);	// rg_pe1_pipe_cmd_frc[4] | ||||
| +#endif | ||||
| +#if defined (CONFIG_PCIE_PORT1) | ||||
| +	/* PCIe Port 1 */ | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x12c), 12, 1, 0x01);	// rg_pe1_pipe_rst_b | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x12c),  4, 1, 0x01);	// rg_pe1_pipe_cmd_frc[4] | ||||
| +#endif | ||||
| +#if defined (CONFIG_PCIE_PORT2) | ||||
| +	/* PCIe Port 2 */ | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x02c), 12, 1, 0x01);	// rg_pe1_pipe_rst_b | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x02c),  4, 1, 0x01);	// rg_pe1_pipe_cmd_frc[4] | ||||
| +#endif | ||||
| +} | ||||
| + | ||||
| +void | ||||
| +set_phy_for_ssc(void) | ||||
| +{ | ||||
| +	unsigned long reg = (*(volatile u32 *)(RALINK_SYSCTL_BASE + 0x10)); | ||||
| + | ||||
| +	reg = (reg >> 6) & 0x7; | ||||
| +#if defined (CONFIG_PCIE_PORT0) || defined (CONFIG_PCIE_PORT1) | ||||
| +	/* Set PCIe Port0 & Port1 PHY to disable SSC */ | ||||
| +	/* Debug Xtal Type */ | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x400),  8, 1, 0x01);	// rg_pe1_frc_h_xtal_type | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x400),  9, 2, 0x00);	// rg_pe1_h_xtal_type | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x000),  4, 1, 0x01);	// rg_pe1_frc_phy_en               //Force Port 0 enable control | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x100),  4, 1, 0x01);	// rg_pe1_frc_phy_en               //Force Port 1 enable control | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x000),  5, 1, 0x00);	// rg_pe1_phy_en                   //Port 0 disable | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x100),  5, 1, 0x00);	// rg_pe1_phy_en                   //Port 1 disable | ||||
| +	if(reg <= 5 && reg >= 3) { 	// 40MHz Xtal | ||||
| +		set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490),  6, 2, 0x01);	// RG_PE1_H_PLL_PREDIV             //Pre-divider ratio (for host mode) | ||||
| +		printk("***** Xtal 40MHz *****\n"); | ||||
| +	} else {			// 25MHz | 20MHz Xtal | ||||
| +		set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490),  6, 2, 0x00);	// RG_PE1_H_PLL_PREDIV             //Pre-divider ratio (for host mode) | ||||
| +		if (reg >= 6) { 	 | ||||
| +			printk("***** Xtal 25MHz *****\n"); | ||||
| +			set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4bc),  4, 2, 0x01);	// RG_PE1_H_PLL_FBKSEL             //Feedback clock select | ||||
| +			set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x49c),  0,31, 0x18000000);	// RG_PE1_H_LCDDS_PCW_NCPO         //DDS NCPO PCW (for host mode) | ||||
| +			set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a4),  0,16, 0x18d);	// RG_PE1_H_LCDDS_SSC_PRD          //DDS SSC dither period control | ||||
| +			set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a8),  0,12, 0x4a);	// RG_PE1_H_LCDDS_SSC_DELTA        //DDS SSC dither amplitude control | ||||
| +			set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a8), 16,12, 0x4a);	// RG_PE1_H_LCDDS_SSC_DELTA1       //DDS SSC dither amplitude control for initial | ||||
| +		} else { | ||||
| +			printk("***** Xtal 20MHz *****\n"); | ||||
| +		} | ||||
| +	} | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4a0),  5, 1, 0x01);	// RG_PE1_LCDDS_CLK_PH_INV         //DDS clock inversion | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 22, 2, 0x02);	// RG_PE1_H_PLL_BC                  | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 18, 4, 0x06);	// RG_PE1_H_PLL_BP                  | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490), 12, 4, 0x02);	// RG_PE1_H_PLL_IR                  | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490),  8, 4, 0x01);	// RG_PE1_H_PLL_IC                  | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x4ac), 16, 3, 0x00);	// RG_PE1_H_PLL_BR                  | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x490),  1, 3, 0x02);	// RG_PE1_PLL_DIVEN                 | ||||
| +	if(reg <= 5 && reg >= 3) { 	// 40MHz Xtal | ||||
| +		set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x414),  6, 2, 0x01);	// rg_pe1_mstckdiv		//value of da_pe1_mstckdiv when force mode enable | ||||
| +		set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x414),  5, 1, 0x01);	// rg_pe1_frc_mstckdiv          //force mode enable of da_pe1_mstckdiv       | ||||
| +	} | ||||
| +	/* Enable PHY and disable force mode */ | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x000),  5, 1, 0x01);	// rg_pe1_phy_en                   //Port 0 enable | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x100),  5, 1, 0x01);	// rg_pe1_phy_en                   //Port 1 enable | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x000),  4, 1, 0x00);	// rg_pe1_frc_phy_en               //Force Port 0 disable control | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P0P1_CTL_OFFSET + 0x100),  4, 1, 0x00);	// rg_pe1_frc_phy_en               //Force Port 1 disable control | ||||
| +#endif | ||||
| +#if defined (CONFIG_PCIE_PORT2) | ||||
| +	/* Set PCIe Port2 PHY to disable SSC */ | ||||
| +	/* Debug Xtal Type */ | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x400),  8, 1, 0x01);	// rg_pe1_frc_h_xtal_type | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x400),  9, 2, 0x00);	// rg_pe1_h_xtal_type | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x000),  4, 1, 0x01);	// rg_pe1_frc_phy_en               //Force Port 0 enable control | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x000),  5, 1, 0x00);	// rg_pe1_phy_en                   //Port 0 disable | ||||
| +	if(reg <= 5 && reg >= 3) { 	// 40MHz Xtal | ||||
| +		set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490),  6, 2, 0x01);	// RG_PE1_H_PLL_PREDIV             //Pre-divider ratio (for host mode) | ||||
| +	} else {			// 25MHz | 20MHz Xtal | ||||
| +		set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490),  6, 2, 0x00);	// RG_PE1_H_PLL_PREDIV             //Pre-divider ratio (for host mode) | ||||
| +		if (reg >= 6) { 	// 25MHz Xtal | ||||
| +			set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4bc),  4, 2, 0x01);	// RG_PE1_H_PLL_FBKSEL             //Feedback clock select | ||||
| +			set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x49c),  0,31, 0x18000000);	// RG_PE1_H_LCDDS_PCW_NCPO         //DDS NCPO PCW (for host mode) | ||||
| +			set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a4),  0,16, 0x18d);	// RG_PE1_H_LCDDS_SSC_PRD          //DDS SSC dither period control | ||||
| +			set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a8),  0,12, 0x4a);	// RG_PE1_H_LCDDS_SSC_DELTA        //DDS SSC dither amplitude control | ||||
| +			set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a8), 16,12, 0x4a);	// RG_PE1_H_LCDDS_SSC_DELTA1       //DDS SSC dither amplitude control for initial | ||||
| +		} | ||||
| +	} | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4a0),  5, 1, 0x01);	// RG_PE1_LCDDS_CLK_PH_INV         //DDS clock inversion | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 22, 2, 0x02);	// RG_PE1_H_PLL_BC                  | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 18, 4, 0x06);	// RG_PE1_H_PLL_BP                  | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490), 12, 4, 0x02);	// RG_PE1_H_PLL_IR                  | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490),  8, 4, 0x01);	// RG_PE1_H_PLL_IC                  | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x4ac), 16, 3, 0x00);	// RG_PE1_H_PLL_BR                  | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x490),  1, 3, 0x02);	// RG_PE1_PLL_DIVEN                 | ||||
| +	if(reg <= 5 && reg >= 3) { 	// 40MHz Xtal | ||||
| +		set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x414),  6, 2, 0x01);	// rg_pe1_mstckdiv		//value of da_pe1_mstckdiv when force mode enable | ||||
| +		set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x414),  5, 1, 0x01);	// rg_pe1_frc_mstckdiv          //force mode enable of da_pe1_mstckdiv       | ||||
| +	} | ||||
| +	/* Enable PHY and disable force mode */ | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x000),  5, 1, 0x01);	// rg_pe1_phy_en                   //Port 0 enable | ||||
| +	set_pcie_phy((u32 *)(RALINK_PCIEPHY_P2_CTL_OFFSET + 0x000),  4, 1, 0x00);	// rg_pe1_frc_phy_en               //Force Port 0 disable control | ||||
| +#endif | ||||
| +} | ||||
| + | ||||
| +void setup_cm_memory_region(struct resource *mem_resource) | ||||
| +{ | ||||
| +	resource_size_t mask; | ||||
| +	if (mips_cm_numiocu()) { | ||||
| +		/* FIXME: hardware doesn't accept mask values with 1s after | ||||
| +		   0s (e.g. 0xffef), so it would be great to warn if that's | ||||
| +		   about to happen */ | ||||
| +		mask = ~(mem_resource->end - mem_resource->start); | ||||
| + | ||||
| +		write_gcr_reg1_base(mem_resource->start); | ||||
| +		write_gcr_reg1_mask(mask | CM_GCR_REGn_MASK_CMTGT_IOCU0); | ||||
| +		printk("PCI coherence region base: 0x%08lx, mask/settings: 0x%08lx\n", | ||||
| +		       read_gcr_reg1_base(), | ||||
| +		       read_gcr_reg1_mask()); | ||||
| +	} | ||||
| +} | ||||
| + | ||||
| +static int mt7621_pci_probe(struct platform_device *pdev) | ||||
| +{ | ||||
| +	unsigned long val = 0; | ||||
| + | ||||
| +	iomem_resource.start = 0; | ||||
| +	iomem_resource.end= ~0; | ||||
| +	ioport_resource.start= 0; | ||||
| +	ioport_resource.end = ~0; | ||||
| + | ||||
| +#if defined (CONFIG_PCIE_PORT0) | ||||
| +	val = RALINK_PCIE0_RST; | ||||
| +#endif | ||||
| +#if defined (CONFIG_PCIE_PORT1) | ||||
| +	val |= RALINK_PCIE1_RST; | ||||
| +#endif | ||||
| +#if defined (CONFIG_PCIE_PORT2) | ||||
| +	val |= RALINK_PCIE2_RST; | ||||
| +#endif | ||||
| +	ASSERT_SYSRST_PCIE(RALINK_PCIE0_RST | RALINK_PCIE1_RST | RALINK_PCIE2_RST); | ||||
| +	printk("pull PCIe RST: RALINK_RSTCTRL = %x\n", RALINK_RSTCTRL); | ||||
| +#if defined GPIO_PERST /* add GPIO control instead of PERST_N */ /*chhung*/ | ||||
| +	*(unsigned int *)(0xbe000060) &= ~(0x3<<10 | 0x3<<3); | ||||
| +	*(unsigned int *)(0xbe000060) |= 0x1<<10 | 0x1<<3; | ||||
| +	mdelay(100); | ||||
| +	*(unsigned int *)(0xbe000600) |= 0x1<<19 | 0x1<<8 | 0x1<<7; // use GPIO19/GPIO8/GPIO7 (PERST_N/UART_RXD3/UART_TXD3) | ||||
| +	mdelay(100); | ||||
| +	*(unsigned int *)(0xbe000620) &= ~(0x1<<19 | 0x1<<8 | 0x1<<7);		// clear DATA | ||||
| + | ||||
| +	mdelay(100); | ||||
| +#else | ||||
| +	*(unsigned int *)(0xbe000060) &= ~0x00000c00; | ||||
| +#endif | ||||
| +#if defined (CONFIG_PCIE_PORT0) | ||||
| +	val = RALINK_PCIE0_RST; | ||||
| +#endif | ||||
| +#if defined (CONFIG_PCIE_PORT1) | ||||
| +	val |= RALINK_PCIE1_RST; | ||||
| +#endif | ||||
| +#if defined (CONFIG_PCIE_PORT2) | ||||
| +	val |= RALINK_PCIE2_RST; | ||||
| +#endif | ||||
| +	DEASSERT_SYSRST_PCIE(val); | ||||
| +	printk("release PCIe RST: RALINK_RSTCTRL = %x\n", RALINK_RSTCTRL); | ||||
| + | ||||
| +	if ((*(unsigned int *)(0xbe00000c)&0xFFFF) == 0x0101) // MT7621 E2 | ||||
| +		bypass_pipe_rst(); | ||||
| +	set_phy_for_ssc(); | ||||
| +	printk("release PCIe RST: RALINK_RSTCTRL = %x\n", RALINK_RSTCTRL); | ||||
| + | ||||
| +#if defined (CONFIG_PCIE_PORT0) | ||||
| +	read_config(0, 0, 0, 0x70c, &val); | ||||
| +	printk("Port 0 N_FTS = %x\n", (unsigned int)val); | ||||
| +#endif | ||||
| +#if defined (CONFIG_PCIE_PORT1) | ||||
| +	read_config(0, 1, 0, 0x70c, &val); | ||||
| +	printk("Port 1 N_FTS = %x\n", (unsigned int)val); | ||||
| +#endif | ||||
| +#if defined (CONFIG_PCIE_PORT2) | ||||
| +	read_config(0, 2, 0, 0x70c, &val); | ||||
| +	printk("Port 2 N_FTS = %x\n", (unsigned int)val); | ||||
| +#endif | ||||
| + | ||||
| +	RALINK_RSTCTRL = (RALINK_RSTCTRL | RALINK_PCIE_RST); | ||||
| +	RALINK_SYSCFG1 &= ~(0x30); | ||||
| +	RALINK_SYSCFG1 |= (2<<4); | ||||
| +	RALINK_PCIE_CLK_GEN &= 0x7fffffff; | ||||
| +	RALINK_PCIE_CLK_GEN1 &= 0x80ffffff; | ||||
| +	RALINK_PCIE_CLK_GEN1 |= 0xa << 24; | ||||
| +	RALINK_PCIE_CLK_GEN |= 0x80000000; | ||||
| +	mdelay(50); | ||||
| +	RALINK_RSTCTRL = (RALINK_RSTCTRL & ~RALINK_PCIE_RST); | ||||
| +	 | ||||
| + | ||||
| +#if defined GPIO_PERST /* add GPIO control instead of PERST_N */  /*chhung*/ | ||||
| +	*(unsigned int *)(0xbe000620) |= 0x1<<19 | 0x1<<8 | 0x1<<7;		// set DATA | ||||
| +	mdelay(100); | ||||
| +#else | ||||
| +	RALINK_PCI_PCICFG_ADDR &= ~(1<<1); //de-assert PERST | ||||
| +#endif | ||||
| +	mdelay(500); | ||||
| + | ||||
| + | ||||
| +	mdelay(500); | ||||
| +#if defined (CONFIG_PCIE_PORT0) | ||||
| +	if(( RALINK_PCI0_STATUS & 0x1) == 0) | ||||
| +	{ | ||||
| +		printk("PCIE0 no card, disable it(RST&CLK)\n"); | ||||
| +		ASSERT_SYSRST_PCIE(RALINK_PCIE0_RST); | ||||
| +		RALINK_CLKCFG1 = (RALINK_CLKCFG1 & ~RALINK_PCIE0_CLK_EN); | ||||
| +		pcie_link_status &= ~(1<<0); | ||||
| +	} else { | ||||
| +		pcie_link_status |= 1<<0; | ||||
| +		RALINK_PCI_PCIMSK_ADDR |= (1<<20); // enable pcie1 interrupt | ||||
| +	} | ||||
| +#endif | ||||
| +#if defined (CONFIG_PCIE_PORT1) | ||||
| +	if(( RALINK_PCI1_STATUS & 0x1) == 0) | ||||
| +	{ | ||||
| +		printk("PCIE1 no card, disable it(RST&CLK)\n"); | ||||
| +		ASSERT_SYSRST_PCIE(RALINK_PCIE1_RST); | ||||
| +		RALINK_CLKCFG1 = (RALINK_CLKCFG1 & ~RALINK_PCIE1_CLK_EN); | ||||
| +		pcie_link_status &= ~(1<<1); | ||||
| +	} else { | ||||
| +		pcie_link_status |= 1<<1; | ||||
| +		RALINK_PCI_PCIMSK_ADDR |= (1<<21); // enable pcie1 interrupt | ||||
| +	} | ||||
| +#endif | ||||
| +#if defined (CONFIG_PCIE_PORT2) | ||||
| +	if (( RALINK_PCI2_STATUS & 0x1) == 0) { | ||||
| +		printk("PCIE2 no card, disable it(RST&CLK)\n"); | ||||
| +		ASSERT_SYSRST_PCIE(RALINK_PCIE2_RST); | ||||
| +		RALINK_CLKCFG1 = (RALINK_CLKCFG1 & ~RALINK_PCIE2_CLK_EN); | ||||
| +		pcie_link_status &= ~(1<<2); | ||||
| +	} else { | ||||
| +		pcie_link_status |= 1<<2; | ||||
| +		RALINK_PCI_PCIMSK_ADDR |= (1<<22); // enable pcie2 interrupt | ||||
| +	} | ||||
| +#endif | ||||
| +	if (pcie_link_status == 0) | ||||
| +		return 0; | ||||
| + | ||||
| +/* | ||||
| +pcie(2/1/0) link status	pcie2_num	pcie1_num	pcie0_num | ||||
| +3'b000			x		x		x | ||||
| +3'b001			x		x		0 | ||||
| +3'b010			x		0		x | ||||
| +3'b011			x		1		0 | ||||
| +3'b100			0		x		x | ||||
| +3'b101			1		x		0 | ||||
| +3'b110			1		0		x | ||||
| +3'b111			2		1		0 | ||||
| +*/ | ||||
| +	switch(pcie_link_status) { | ||||
| +	case 2: | ||||
| +		RALINK_PCI_PCICFG_ADDR &= ~0x00ff0000; | ||||
| +		RALINK_PCI_PCICFG_ADDR |= 0x1 << 16;	//port0 | ||||
| +		RALINK_PCI_PCICFG_ADDR |= 0x0 << 20;	//port1 | ||||
| +		break; | ||||
| +	case 4: | ||||
| +		RALINK_PCI_PCICFG_ADDR &= ~0x0fff0000; | ||||
| +		RALINK_PCI_PCICFG_ADDR |= 0x1 << 16;	//port0 | ||||
| +		RALINK_PCI_PCICFG_ADDR |= 0x2 << 20;	//port1 | ||||
| +		RALINK_PCI_PCICFG_ADDR |= 0x0 << 24;	//port2 | ||||
| +		break; | ||||
| +	case 5: | ||||
| +		RALINK_PCI_PCICFG_ADDR &= ~0x0fff0000; | ||||
| +		RALINK_PCI_PCICFG_ADDR |= 0x0 << 16;	//port0 | ||||
| +		RALINK_PCI_PCICFG_ADDR |= 0x2 << 20;	//port1 | ||||
| +		RALINK_PCI_PCICFG_ADDR |= 0x1 << 24;	//port2 | ||||
| +		break; | ||||
| +	case 6: | ||||
| +		RALINK_PCI_PCICFG_ADDR &= ~0x0fff0000; | ||||
| +		RALINK_PCI_PCICFG_ADDR |= 0x2 << 16;	//port0 | ||||
| +		RALINK_PCI_PCICFG_ADDR |= 0x0 << 20;	//port1 | ||||
| +		RALINK_PCI_PCICFG_ADDR |= 0x1 << 24;	//port2 | ||||
| +		break; | ||||
| +	} | ||||
| +	printk(" -> %x\n", RALINK_PCI_PCICFG_ADDR); | ||||
| +	//printk(" RALINK_PCI_ARBCTL = %x\n", RALINK_PCI_ARBCTL); | ||||
| + | ||||
| +/* | ||||
| +	ioport_resource.start = mt7621_res_pci_io1.start; | ||||
| +  	ioport_resource.end = mt7621_res_pci_io1.end; | ||||
| +*/ | ||||
| + | ||||
| +	RALINK_PCI_MEMBASE = 0xffffffff; //RALINK_PCI_MM_MAP_BASE; | ||||
| +	RALINK_PCI_IOBASE = RALINK_PCI_IO_MAP_BASE; | ||||
| + | ||||
| +#if defined (CONFIG_PCIE_PORT0) | ||||
| +	//PCIe0 | ||||
| +	if((pcie_link_status & 0x1) != 0) { | ||||
| +		RALINK_PCI0_BAR0SETUP_ADDR = 0x7FFF0001;	//open 7FFF:2G; ENABLE | ||||
| +		RALINK_PCI0_IMBASEBAR0_ADDR = MEMORY_BASE; | ||||
| +		RALINK_PCI0_CLASS = 0x06040001; | ||||
| +		printk("PCIE0 enabled\n"); | ||||
| +	} | ||||
| +#endif | ||||
| +#if defined (CONFIG_PCIE_PORT1) | ||||
| +	//PCIe1 | ||||
| +	if ((pcie_link_status & 0x2) != 0) { | ||||
| +		RALINK_PCI1_BAR0SETUP_ADDR = 0x7FFF0001;	//open 7FFF:2G; ENABLE | ||||
| +		RALINK_PCI1_IMBASEBAR0_ADDR = MEMORY_BASE; | ||||
| +		RALINK_PCI1_CLASS = 0x06040001; | ||||
| +		printk("PCIE1 enabled\n"); | ||||
| +	} | ||||
| +#endif | ||||
| +#if defined (CONFIG_PCIE_PORT2) | ||||
| +	//PCIe2 | ||||
| +	if ((pcie_link_status & 0x4) != 0) { | ||||
| +		RALINK_PCI2_BAR0SETUP_ADDR = 0x7FFF0001;	//open 7FFF:2G; ENABLE | ||||
| +		RALINK_PCI2_IMBASEBAR0_ADDR = MEMORY_BASE; | ||||
| +		RALINK_PCI2_CLASS = 0x06040001; | ||||
| +		printk("PCIE2 enabled\n"); | ||||
| +	} | ||||
| +#endif | ||||
| + | ||||
| + | ||||
| +	switch(pcie_link_status) { | ||||
| +	case 7: | ||||
| +		read_config(0, 2, 0, 0x4, &val); | ||||
| +		write_config(0, 2, 0, 0x4, val|0x4); | ||||
| +		// write_config(0, 1, 0, 0x4, val|0x7); | ||||
| +		read_config(0, 2, 0, 0x70c, &val); | ||||
| +		val &= ~(0xff)<<8; | ||||
| +		val |= 0x50<<8; | ||||
| +		write_config(0, 2, 0, 0x70c, val); | ||||
| +	case 3: | ||||
| +	case 5: | ||||
| +	case 6: | ||||
| +		read_config(0, 1, 0, 0x4, &val); | ||||
| +		write_config(0, 1, 0, 0x4, val|0x4); | ||||
| +		// write_config(0, 1, 0, 0x4, val|0x7); | ||||
| +		read_config(0, 1, 0, 0x70c, &val); | ||||
| +		val &= ~(0xff)<<8; | ||||
| +		val |= 0x50<<8; | ||||
| +		write_config(0, 1, 0, 0x70c, val); | ||||
| +	default: | ||||
| +		read_config(0, 0, 0, 0x4, &val); | ||||
| +		write_config(0, 0, 0, 0x4, val|0x4); //bus master enable | ||||
| +		// write_config(0, 0, 0, 0x4, val|0x7); //bus master enable | ||||
| +		read_config(0, 0, 0, 0x70c, &val); | ||||
| +		val &= ~(0xff)<<8; | ||||
| +		val |= 0x50<<8; | ||||
| +		write_config(0, 0, 0, 0x70c, val); | ||||
| +	} | ||||
| + | ||||
| +	pci_load_of_ranges(&mt7621_controller, pdev->dev.of_node); | ||||
| +	setup_cm_memory_region(mt7621_controller.mem_resource); | ||||
| +	register_pci_controller(&mt7621_controller); | ||||
| +	return 0; | ||||
| + | ||||
| +} | ||||
| + | ||||
| +int pcibios_plat_dev_init(struct pci_dev *dev) | ||||
| +{ | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static const struct of_device_id mt7621_pci_ids[] = { | ||||
| +	{ .compatible = "mediatek,mt7621-pci" }, | ||||
| +	{}, | ||||
| +}; | ||||
| +MODULE_DEVICE_TABLE(of, mt7621_pci_ids); | ||||
| + | ||||
| +static struct platform_driver mt7621_pci_driver = { | ||||
| +	.probe = mt7621_pci_probe, | ||||
| +	.driver = { | ||||
| +		.name = "mt7621-pci", | ||||
| +		.owner = THIS_MODULE, | ||||
| +		.of_match_table = of_match_ptr(mt7621_pci_ids), | ||||
| +	}, | ||||
| +}; | ||||
| + | ||||
| +static int __init mt7621_pci_init(void) | ||||
| +{ | ||||
| +	return platform_driver_register(&mt7621_pci_driver); | ||||
| +} | ||||
| + | ||||
| +arch_initcall(mt7621_pci_init); | ||||
| @@ -0,0 +1,81 @@ | ||||
| From ce3d4a4111a5f7e6b4e74bceae5faa6ce388e8ec Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <blogic@openwrt.org> | ||||
| Date: Sun, 14 Jul 2013 23:08:11 +0200 | ||||
| Subject: [PATCH 05/53] MIPS: use set_mode() to enable/disable the cevt-r4k | ||||
|  irq | ||||
|  | ||||
| Signed-off-by: John Crispin <blogic@openwrt.org> | ||||
| --- | ||||
|  arch/mips/ralink/Kconfig |    5 +++++ | ||||
|  1 file changed, 5 insertions(+) | ||||
|  | ||||
| --- a/arch/mips/ralink/Kconfig | ||||
| +++ b/arch/mips/ralink/Kconfig | ||||
| @@ -1,11 +1,16 @@ | ||||
|  if RALINK | ||||
|   | ||||
| +config CEVT_SYSTICK_QUIRK | ||||
| +	bool | ||||
| +	default n | ||||
| + | ||||
|  config CLKEVT_RT3352 | ||||
|  	bool | ||||
|  	depends on SOC_RT305X || SOC_MT7620 | ||||
|  	default y | ||||
|  	select CLKSRC_OF | ||||
|  	select CLKSRC_MMIO | ||||
| +	select CEVT_SYSTICK_QUIRK | ||||
|   | ||||
|  config RALINK_ILL_ACC | ||||
|  	bool | ||||
| --- a/arch/mips/kernel/cevt-r4k.c | ||||
| +++ b/arch/mips/kernel/cevt-r4k.c | ||||
| @@ -15,6 +15,26 @@ | ||||
|  #include <asm/time.h> | ||||
|  #include <asm/cevt-r4k.h> | ||||
|   | ||||
| +static int mips_state_oneshot(struct clock_event_device *evt) | ||||
| +{ | ||||
| +	if (!cp0_timer_irq_installed) { | ||||
| +		cp0_timer_irq_installed = 1; | ||||
| +		setup_irq(evt->irq, &c0_compare_irqaction); | ||||
| +	} | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static int mips_state_shutdown(struct clock_event_device *evt) | ||||
| +{ | ||||
| +	if (cp0_timer_irq_installed) { | ||||
| +		cp0_timer_irq_installed = 0; | ||||
| +		remove_irq(evt->irq, &c0_compare_irqaction); | ||||
| +	} | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
|  static int mips_next_event(unsigned long delta, | ||||
|  			   struct clock_event_device *evt) | ||||
|  { | ||||
| @@ -281,17 +301,21 @@ int r4k_clockevent_init(void) | ||||
|  	cd->rating		= 300; | ||||
|  	cd->irq			= irq; | ||||
|  	cd->cpumask		= cpumask_of(cpu); | ||||
| +	cd->set_state_shutdown	= mips_state_shutdown; | ||||
| +	cd->set_state_oneshot	= mips_state_oneshot; | ||||
|  	cd->set_next_event	= mips_next_event; | ||||
|  	cd->event_handler	= mips_event_handler; | ||||
|   | ||||
|  	clockevents_config_and_register(cd, mips_hpt_frequency, min_delta, 0x7fffffff); | ||||
|   | ||||
| +#ifndef CONFIG_CEVT_SYSTICK_QUIRK | ||||
|  	if (cp0_timer_irq_installed) | ||||
|  		return 0; | ||||
|   | ||||
|  	cp0_timer_irq_installed = 1; | ||||
|   | ||||
|  	setup_irq(irq, &c0_compare_irqaction); | ||||
| +#endif | ||||
|   | ||||
|  	return 0; | ||||
|  } | ||||
| @@ -0,0 +1,198 @@ | ||||
| From bd30f19a006fb52bac80c6463c49dd2f4159f4ac Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <blogic@openwrt.org> | ||||
| Date: Sun, 28 Jul 2013 16:26:41 +0200 | ||||
| Subject: [PATCH 06/53] MIPS: ralink: add cpu frequency scaling | ||||
|  | ||||
| This feature will break udelay() and cause the delay loop to have longer delays | ||||
| when the frequency is scaled causing a performance hit. | ||||
|  | ||||
| Signed-off-by: John Crispin <blogic@openwrt.org> | ||||
| --- | ||||
|  arch/mips/ralink/cevt-rt3352.c |   38 ++++++++++++++++++++++++++++++++++++++ | ||||
|  1 file changed, 38 insertions(+) | ||||
|  | ||||
| --- a/arch/mips/ralink/cevt-rt3352.c | ||||
| +++ b/arch/mips/ralink/cevt-rt3352.c | ||||
| @@ -29,6 +29,10 @@ | ||||
|  /* enable the counter */ | ||||
|  #define CFG_CNT_EN		0x1 | ||||
|   | ||||
| +/* mt7620 frequency scaling defines */ | ||||
| +#define CLK_LUT_CFG	0x40 | ||||
| +#define SLEEP_EN	BIT(31) | ||||
| + | ||||
|  struct systick_device { | ||||
|  	void __iomem *membase; | ||||
|  	struct clock_event_device dev; | ||||
| @@ -36,21 +40,53 @@ struct systick_device { | ||||
|  	int freq_scale; | ||||
|  }; | ||||
|   | ||||
| +static void (*systick_freq_scaling)(struct systick_device *sdev, int status); | ||||
| + | ||||
|  static int systick_set_oneshot(struct clock_event_device *evt); | ||||
|  static int systick_shutdown(struct clock_event_device *evt); | ||||
|   | ||||
| +static inline void mt7620_freq_scaling(struct systick_device *sdev, int status) | ||||
| +{ | ||||
| +	if (sdev->freq_scale == status) | ||||
| +		return; | ||||
| + | ||||
| +	sdev->freq_scale = status; | ||||
| + | ||||
| +	pr_info("%s: %s autosleep mode\n", sdev->dev.name, | ||||
| +			(status) ? ("enable") : ("disable")); | ||||
| +	if (status) | ||||
| +		rt_sysc_w32(rt_sysc_r32(CLK_LUT_CFG) | SLEEP_EN, CLK_LUT_CFG); | ||||
| +	else | ||||
| +		rt_sysc_w32(rt_sysc_r32(CLK_LUT_CFG) & ~SLEEP_EN, CLK_LUT_CFG); | ||||
| +} | ||||
| + | ||||
| +static inline unsigned int read_count(struct systick_device *sdev) | ||||
| +{ | ||||
| +	return ioread32(sdev->membase + SYSTICK_COUNT); | ||||
| +} | ||||
| + | ||||
| +static inline unsigned int read_compare(struct systick_device *sdev) | ||||
| +{ | ||||
| +	return ioread32(sdev->membase + SYSTICK_COMPARE); | ||||
| +} | ||||
| + | ||||
| +static inline void write_compare(struct systick_device *sdev, unsigned int val) | ||||
| +{ | ||||
| +	iowrite32(val, sdev->membase + SYSTICK_COMPARE); | ||||
| +} | ||||
| + | ||||
|  static int systick_next_event(unsigned long delta, | ||||
|  				struct clock_event_device *evt) | ||||
|  { | ||||
|  	struct systick_device *sdev; | ||||
| -	u32 count; | ||||
| +	int res; | ||||
|   | ||||
|  	sdev = container_of(evt, struct systick_device, dev); | ||||
| -	count = ioread32(sdev->membase + SYSTICK_COUNT); | ||||
| -	count = (count + delta) % SYSTICK_FREQ; | ||||
| -	iowrite32(count, sdev->membase + SYSTICK_COMPARE); | ||||
| +	delta += read_count(sdev); | ||||
| +	write_compare(sdev, delta); | ||||
| +	res = ((int)(read_count(sdev) - delta) >= 0) ? -ETIME : 0; | ||||
|   | ||||
| -	return 0; | ||||
| +	return res; | ||||
|  } | ||||
|   | ||||
|  static void systick_event_handler(struct clock_event_device *dev) | ||||
| @@ -60,20 +96,25 @@ static void systick_event_handler(struct | ||||
|   | ||||
|  static irqreturn_t systick_interrupt(int irq, void *dev_id) | ||||
|  { | ||||
| -	struct clock_event_device *dev = (struct clock_event_device *) dev_id; | ||||
| +	int ret = 0; | ||||
| +	struct clock_event_device *cdev; | ||||
| +	struct systick_device *sdev; | ||||
|   | ||||
| -	dev->event_handler(dev); | ||||
| +	if (read_c0_cause() & STATUSF_IP7) { | ||||
| +		cdev = (struct clock_event_device *) dev_id; | ||||
| +		sdev = container_of(cdev, struct systick_device, dev); | ||||
| + | ||||
| +		/* Clear Count/Compare Interrupt */ | ||||
| +		write_compare(sdev, read_compare(sdev)); | ||||
| +		cdev->event_handler(cdev); | ||||
| +		ret = 1; | ||||
| +	} | ||||
|   | ||||
| -	return IRQ_HANDLED; | ||||
| +	return IRQ_RETVAL(ret); | ||||
|  } | ||||
|   | ||||
|  static struct systick_device systick = { | ||||
|  	.dev = { | ||||
| -		/* | ||||
| -		 * cevt-r4k uses 300, make sure systick | ||||
| -		 * gets used if available | ||||
| -		 */ | ||||
| -		.rating			= 310, | ||||
|  		.features		= CLOCK_EVT_FEAT_ONESHOT, | ||||
|  		.set_next_event		= systick_next_event, | ||||
|  		.set_state_shutdown	= systick_shutdown, | ||||
| @@ -95,9 +136,15 @@ static int systick_shutdown(struct clock | ||||
|  	sdev = container_of(evt, struct systick_device, dev); | ||||
|   | ||||
|  	if (sdev->irq_requested) | ||||
| -		free_irq(systick.dev.irq, &systick_irqaction); | ||||
| +		remove_irq(systick.dev.irq, &systick_irqaction); | ||||
|  	sdev->irq_requested = 0; | ||||
| -	iowrite32(0, systick.membase + SYSTICK_CONFIG); | ||||
| +	iowrite32(CFG_CNT_EN, systick.membase + SYSTICK_CONFIG); | ||||
| + | ||||
| +	if (systick_freq_scaling) | ||||
| +		systick_freq_scaling(sdev, 0); | ||||
| + | ||||
| +	if (systick_freq_scaling) | ||||
| +		systick_freq_scaling(sdev, 1); | ||||
|   | ||||
|  	return 0; | ||||
|  } | ||||
| @@ -117,32 +164,48 @@ static int systick_set_oneshot(struct cl | ||||
|  	return 0; | ||||
|  } | ||||
|   | ||||
| +static const struct of_device_id systick_match[] = { | ||||
| +	{ .compatible = "ralink,mt7620a-systick", .data = mt7620_freq_scaling}, | ||||
| +	{}, | ||||
| +}; | ||||
| + | ||||
|  static int __init ralink_systick_init(struct device_node *np) | ||||
|  { | ||||
| +	const struct of_device_id *match; | ||||
| +	int rating = 200; | ||||
|  	int ret; | ||||
|   | ||||
|  	systick.membase = of_iomap(np, 0); | ||||
|  	if (!systick.membase) | ||||
|  		return -ENXIO; | ||||
|   | ||||
| -	systick_irqaction.name = np->name; | ||||
| -	systick.dev.name = np->name; | ||||
| -	clockevents_calc_mult_shift(&systick.dev, SYSTICK_FREQ, 60); | ||||
| -	systick.dev.max_delta_ns = clockevent_delta2ns(0x7fff, &systick.dev); | ||||
| -	systick.dev.min_delta_ns = clockevent_delta2ns(0x3, &systick.dev); | ||||
| +	match = of_match_node(systick_match, np); | ||||
| +	if (match) { | ||||
| +		systick_freq_scaling = match->data; | ||||
| +		/* | ||||
| +		 * cevt-r4k uses 300, make sure systick | ||||
| +		 * gets used if available | ||||
| +		 */ | ||||
| +		rating = 310; | ||||
| +	} | ||||
| + | ||||
| +	/* enable counter than register clock source */ | ||||
| +	iowrite32(CFG_CNT_EN, systick.membase + SYSTICK_CONFIG); | ||||
| +	clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name, | ||||
| +			SYSTICK_FREQ, rating, 16, clocksource_mmio_readl_up); | ||||
| + | ||||
| +	/* register clock event */ | ||||
|  	systick.dev.irq = irq_of_parse_and_map(np, 0); | ||||
|  	if (!systick.dev.irq) { | ||||
|  		pr_err("%s: request_irq failed", np->name); | ||||
|  		return -EINVAL; | ||||
|  	} | ||||
|   | ||||
| -	ret = clocksource_mmio_init(systick.membase + SYSTICK_COUNT, np->name, | ||||
| -				    SYSTICK_FREQ, 301, 16, | ||||
| -				    clocksource_mmio_readl_up); | ||||
| -	if (ret) | ||||
| -		return ret; | ||||
| - | ||||
| -	clockevents_register_device(&systick.dev); | ||||
| +	systick_irqaction.name = np->name; | ||||
| +	systick.dev.name = np->name; | ||||
| +	systick.dev.rating = rating; | ||||
| +	systick.dev.cpumask = cpumask_of(0); | ||||
| +	clockevents_config_and_register(&systick.dev, SYSTICK_FREQ, 0x3, 0x7fff); | ||||
|   | ||||
|  	pr_info("%s: running - mult: %d, shift: %d\n", | ||||
|  			np->name, systick.dev.mult, systick.dev.shift); | ||||
| @@ -0,0 +1,21 @@ | ||||
| From 67b7bff0fd364c194e653f69baa623ba2141bd4c Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <blogic@openwrt.org> | ||||
| Date: Mon, 4 Aug 2014 18:46:02 +0200 | ||||
| Subject: [PATCH 07/53] MIPS: ralink: copy the commandline from the devicetree | ||||
|  | ||||
| Signed-off-by: John Crispin <blogic@openwrt.org> | ||||
| --- | ||||
|  arch/mips/ralink/of.c |    2 ++ | ||||
|  1 file changed, 2 insertions(+) | ||||
|  | ||||
| --- a/arch/mips/ralink/of.c | ||||
| +++ b/arch/mips/ralink/of.c | ||||
| @@ -74,6 +74,8 @@ void __init plat_mem_setup(void) | ||||
|  	 */ | ||||
|  	__dt_setup_arch(__dtb_start); | ||||
|   | ||||
| +	strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE); | ||||
| + | ||||
|  	of_scan_flat_dt(early_init_dt_find_memory, NULL); | ||||
|  	if (memory_dtb) | ||||
|  		of_scan_flat_dt(early_init_dt_scan_memory, NULL); | ||||
| @@ -0,0 +1,28 @@ | ||||
| From 5ede027f6c4a57ed25da872420508b7f1168b36b Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <blogic@openwrt.org> | ||||
| Date: Mon, 7 Dec 2015 17:15:32 +0100 | ||||
| Subject: [PATCH 13/53] owrt: hack: fix mt7688 cache issue | ||||
|  | ||||
| Signed-off-by: John Crispin <blogic@openwrt.org> | ||||
| --- | ||||
|  arch/mips/kernel/setup.c |    2 +- | ||||
|  1 file changed, 1 insertion(+), 1 deletion(-) | ||||
|  | ||||
| --- a/arch/mips/kernel/setup.c | ||||
| +++ b/arch/mips/kernel/setup.c | ||||
| @@ -774,7 +774,6 @@ static void __init arch_mem_init(char ** | ||||
|  				crashk_res.end - crashk_res.start + 1, | ||||
|  				BOOTMEM_DEFAULT); | ||||
|  #endif | ||||
| -	device_tree_init(); | ||||
|  	sparse_init(); | ||||
|  	plat_swiotlb_setup(); | ||||
|   | ||||
| @@ -890,6 +889,7 @@ void __init setup_arch(char **cmdline_p) | ||||
|   | ||||
|  	cpu_cache_init(); | ||||
|  	paging_init(); | ||||
| +	device_tree_init(); | ||||
|  } | ||||
|   | ||||
|  unsigned long kernelsp[NR_CPUS]; | ||||
| @@ -0,0 +1,25 @@ | ||||
| From 9e6ce539092a1dd605a20bf73c655a9de58d8641 Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <blogic@openwrt.org> | ||||
| Date: Mon, 7 Dec 2015 17:18:05 +0100 | ||||
| Subject: [PATCH 15/53] arch: mips: do not select illegal access driver by | ||||
|  default | ||||
|  | ||||
| Signed-off-by: John Crispin <blogic@openwrt.org> | ||||
| --- | ||||
|  arch/mips/ralink/Kconfig |    4 ++-- | ||||
|  1 file changed, 2 insertions(+), 2 deletions(-) | ||||
|  | ||||
| --- a/arch/mips/ralink/Kconfig | ||||
| +++ b/arch/mips/ralink/Kconfig | ||||
| @@ -13,9 +13,9 @@ config CLKEVT_RT3352 | ||||
|  	select CEVT_SYSTICK_QUIRK | ||||
|   | ||||
|  config RALINK_ILL_ACC | ||||
| -	bool | ||||
| +	bool "illegal access irq" | ||||
|  	depends on SOC_RT305X | ||||
| -	default y | ||||
| +	default n | ||||
|   | ||||
|  config IRQ_INTC | ||||
|  	bool | ||||
| @@ -0,0 +1,166 @@ | ||||
| From 4267880319bc1a2270d352e0ded6d6386242a7ef Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <blogic@openwrt.org> | ||||
| Date: Tue, 12 Aug 2014 20:49:27 +0200 | ||||
| Subject: [PATCH 24/53] GPIO: add named gpio exports | ||||
|  | ||||
| Signed-off-by: John Crispin <blogic@openwrt.org> | ||||
| --- | ||||
|  drivers/gpio/gpiolib-of.c     |   68 +++++++++++++++++++++++++++++++++++++++++ | ||||
|  drivers/gpio/gpiolib-sysfs.c  |   10 +++++- | ||||
|  include/asm-generic/gpio.h    |    6 ++++ | ||||
|  include/linux/gpio/consumer.h |    8 +++++ | ||||
|  4 files changed, 91 insertions(+), 1 deletion(-) | ||||
|  | ||||
| --- a/drivers/gpio/gpiolib-of.c | ||||
| +++ b/drivers/gpio/gpiolib-of.c | ||||
| @@ -23,6 +23,8 @@ | ||||
|  #include <linux/pinctrl/pinctrl.h> | ||||
|  #include <linux/slab.h> | ||||
|  #include <linux/gpio/machine.h> | ||||
| +#include <linux/init.h> | ||||
| +#include <linux/platform_device.h> | ||||
|   | ||||
|  #include "gpiolib.h" | ||||
|   | ||||
| @@ -538,3 +540,69 @@ void of_gpiochip_remove(struct gpio_chip | ||||
|  	gpiochip_remove_pin_ranges(chip); | ||||
|  	of_node_put(chip->of_node); | ||||
|  } | ||||
| + | ||||
| +static struct of_device_id gpio_export_ids[] = { | ||||
| +	{ .compatible = "gpio-export" }, | ||||
| +	{ /* sentinel */ } | ||||
| +}; | ||||
| + | ||||
| +static int __init of_gpio_export_probe(struct platform_device *pdev) | ||||
| +{ | ||||
| +	struct device_node *np = pdev->dev.of_node; | ||||
| +	struct device_node *cnp; | ||||
| +	u32 val; | ||||
| +	int nb = 0; | ||||
| + | ||||
| +	for_each_child_of_node(np, cnp) { | ||||
| +		const char *name = NULL; | ||||
| +		int gpio; | ||||
| +		bool dmc; | ||||
| +		int max_gpio = 1; | ||||
| +		int i; | ||||
| + | ||||
| +		of_property_read_string(cnp, "gpio-export,name", &name); | ||||
| + | ||||
| +		if (!name) | ||||
| +			max_gpio = of_gpio_count(cnp); | ||||
| + | ||||
| +		for (i = 0; i < max_gpio; i++) { | ||||
| +			unsigned flags = 0; | ||||
| +			enum of_gpio_flags of_flags; | ||||
| + | ||||
| +			gpio = of_get_gpio_flags(cnp, i, &of_flags); | ||||
| + | ||||
| +			if (of_flags == OF_GPIO_ACTIVE_LOW) | ||||
| +				flags |= GPIOF_ACTIVE_LOW; | ||||
| + | ||||
| +			if (!of_property_read_u32(cnp, "gpio-export,output", &val)) | ||||
| +				flags |= val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW; | ||||
| +			else | ||||
| +				flags |= GPIOF_IN; | ||||
| + | ||||
| +			if (devm_gpio_request_one(&pdev->dev, gpio, flags, name ? name : of_node_full_name(np))) | ||||
| +				continue; | ||||
| + | ||||
| +			dmc = of_property_read_bool(cnp, "gpio-export,direction_may_change"); | ||||
| +			gpio_export_with_name(gpio, dmc, name); | ||||
| +			nb++; | ||||
| +		} | ||||
| +	} | ||||
| + | ||||
| +	dev_info(&pdev->dev, "%d gpio(s) exported\n", nb); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static struct platform_driver gpio_export_driver = { | ||||
| +	.driver		= { | ||||
| +		.name		= "gpio-export", | ||||
| +		.owner	= THIS_MODULE, | ||||
| +		.of_match_table	= of_match_ptr(gpio_export_ids), | ||||
| +	}, | ||||
| +}; | ||||
| + | ||||
| +static int __init of_gpio_export_init(void) | ||||
| +{ | ||||
| +	return platform_driver_probe(&gpio_export_driver, of_gpio_export_probe); | ||||
| +} | ||||
| +device_initcall(of_gpio_export_init); | ||||
| --- a/drivers/gpio/gpiolib-sysfs.c | ||||
| +++ b/drivers/gpio/gpiolib-sysfs.c | ||||
| @@ -544,7 +544,7 @@ static struct class gpio_class = { | ||||
|   * | ||||
|   * Returns zero on success, else an error. | ||||
|   */ | ||||
| -int gpiod_export(struct gpio_desc *desc, bool direction_may_change) | ||||
| +int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name) | ||||
|  { | ||||
|  	struct gpio_chip	*chip; | ||||
|  	struct gpio_device	*gdev; | ||||
| @@ -606,6 +606,8 @@ int gpiod_export(struct gpio_desc *desc, | ||||
|  	offset = gpio_chip_hwgpio(desc); | ||||
|  	if (chip->names && chip->names[offset]) | ||||
|  		ioname = chip->names[offset]; | ||||
| +	if (name) | ||||
| +		ioname = name; | ||||
|   | ||||
|  	dev = device_create_with_groups(&gpio_class, &gdev->dev, | ||||
|  					MKDEV(0, 0), data, gpio_groups, | ||||
| @@ -627,6 +629,12 @@ err_unlock: | ||||
|  	gpiod_dbg(desc, "%s: status %d\n", __func__, status); | ||||
|  	return status; | ||||
|  } | ||||
| +EXPORT_SYMBOL_GPL(__gpiod_export); | ||||
| + | ||||
| +int gpiod_export(struct gpio_desc *desc, bool direction_may_change) | ||||
| +{ | ||||
| +	return __gpiod_export(desc, direction_may_change, NULL); | ||||
| +} | ||||
|  EXPORT_SYMBOL_GPL(gpiod_export); | ||||
|   | ||||
|  static int match_export(struct device *dev, const void *desc) | ||||
| --- a/include/asm-generic/gpio.h | ||||
| +++ b/include/asm-generic/gpio.h | ||||
| @@ -126,6 +126,12 @@ static inline int gpio_export(unsigned g | ||||
|  	return gpiod_export(gpio_to_desc(gpio), direction_may_change); | ||||
|  } | ||||
|   | ||||
| +int __gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name); | ||||
| +static inline int gpio_export_with_name(unsigned gpio, bool direction_may_change, const char *name) | ||||
| +{ | ||||
| +	return __gpiod_export(gpio_to_desc(gpio), direction_may_change, name); | ||||
| +} | ||||
| + | ||||
|  static inline int gpio_export_link(struct device *dev, const char *name, | ||||
|  				   unsigned gpio) | ||||
|  { | ||||
| --- a/include/linux/gpio/consumer.h | ||||
| +++ b/include/linux/gpio/consumer.h | ||||
| @@ -427,6 +427,7 @@ static inline struct gpio_desc *devm_get | ||||
|   | ||||
|  #if IS_ENABLED(CONFIG_GPIOLIB) && IS_ENABLED(CONFIG_GPIO_SYSFS) | ||||
|   | ||||
| +int _gpiod_export(struct gpio_desc *desc, bool direction_may_change, const char *name); | ||||
|  int gpiod_export(struct gpio_desc *desc, bool direction_may_change); | ||||
|  int gpiod_export_link(struct device *dev, const char *name, | ||||
|  		      struct gpio_desc *desc); | ||||
| @@ -434,6 +435,13 @@ void gpiod_unexport(struct gpio_desc *de | ||||
|   | ||||
|  #else  /* CONFIG_GPIOLIB && CONFIG_GPIO_SYSFS */ | ||||
|   | ||||
| +static inline int _gpiod_export(struct gpio_desc *desc, | ||||
| +			       bool direction_may_change, | ||||
| +			       const char *name) | ||||
| +{ | ||||
| +	return -ENOSYS; | ||||
| +} | ||||
| + | ||||
|  static inline int gpiod_export(struct gpio_desc *desc, | ||||
|  			       bool direction_may_change) | ||||
|  { | ||||
| @@ -0,0 +1,524 @@ | ||||
| From 7adbe9a88c33c6e362a10b109d963b5500a21f00 Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <blogic@openwrt.org> | ||||
| Date: Sun, 27 Jul 2014 09:34:05 +0100 | ||||
| Subject: [PATCH 25/53] pinctrl: ralink: add pinctrl driver | ||||
|  | ||||
| Signed-off-by: John Crispin <blogic@openwrt.org> | ||||
| --- | ||||
|  arch/mips/Kconfig                |    2 + | ||||
|  drivers/pinctrl/Kconfig          |    5 + | ||||
|  drivers/pinctrl/Makefile         |    1 + | ||||
|  drivers/pinctrl/pinctrl-rt2880.c |  474 ++++++++++++++++++++++++++++++++++++++ | ||||
|  4 files changed, 482 insertions(+) | ||||
|  create mode 100644 drivers/pinctrl/pinctrl-rt2880.c | ||||
|  | ||||
| --- a/arch/mips/Kconfig | ||||
| +++ b/arch/mips/Kconfig | ||||
| @@ -617,6 +617,8 @@ config RALINK | ||||
|  	select CLKDEV_LOOKUP | ||||
|  	select ARCH_HAS_RESET_CONTROLLER | ||||
|  	select RESET_CONTROLLER | ||||
| +	select PINCTRL | ||||
| +	select PINCTRL_RT2880 | ||||
|   | ||||
|  config SGI_IP22 | ||||
|  	bool "SGI IP22 (Indy/Indigo2)" | ||||
| --- a/drivers/pinctrl/Kconfig | ||||
| +++ b/drivers/pinctrl/Kconfig | ||||
| @@ -114,6 +114,11 @@ config PINCTRL_LPC18XX | ||||
|  	help | ||||
|  	  Pinctrl driver for NXP LPC18xx/43xx System Control Unit (SCU). | ||||
|   | ||||
| +config PINCTRL_RT2880 | ||||
| +	bool | ||||
| +	depends on RALINK | ||||
| +	select PINMUX | ||||
| + | ||||
|  config PINCTRL_FALCON | ||||
|  	bool | ||||
|  	depends on SOC_FALCON | ||||
| --- a/drivers/pinctrl/Makefile | ||||
| +++ b/drivers/pinctrl/Makefile | ||||
| @@ -23,6 +23,7 @@ obj-$(CONFIG_PINCTRL_PALMAS)	+= pinctrl- | ||||
|  obj-$(CONFIG_PINCTRL_PIC32)	+= pinctrl-pic32.o | ||||
|  obj-$(CONFIG_PINCTRL_PISTACHIO)	+= pinctrl-pistachio.o | ||||
|  obj-$(CONFIG_PINCTRL_ROCKCHIP)	+= pinctrl-rockchip.o | ||||
| +obj-$(CONFIG_PINCTRL_RT2880)	+= pinctrl-rt2880.o | ||||
|  obj-$(CONFIG_PINCTRL_SINGLE)	+= pinctrl-single.o | ||||
|  obj-$(CONFIG_PINCTRL_SIRF)	+= sirf/ | ||||
|  obj-$(CONFIG_ARCH_TEGRA)	+= tegra/ | ||||
| --- /dev/null | ||||
| +++ b/drivers/pinctrl/pinctrl-rt2880.c | ||||
| @@ -0,0 +1,472 @@ | ||||
| +/* | ||||
| + *  linux/drivers/pinctrl/pinctrl-rt2880.c | ||||
| + * | ||||
| + *  This program is free software; you can redistribute it and/or modify | ||||
| + *  it under the terms of the GNU General Public License version 2 as | ||||
| + *  publishhed by the Free Software Foundation. | ||||
| + * | ||||
| + *  Copyright (C) 2013 John Crispin <blogic@openwrt.org> | ||||
| + */ | ||||
| + | ||||
| +#include <linux/module.h> | ||||
| +#include <linux/device.h> | ||||
| +#include <linux/io.h> | ||||
| +#include <linux/platform_device.h> | ||||
| +#include <linux/slab.h> | ||||
| +#include <linux/of.h> | ||||
| +#include <linux/pinctrl/pinctrl.h> | ||||
| +#include <linux/pinctrl/pinconf.h> | ||||
| +#include <linux/pinctrl/pinmux.h> | ||||
| +#include <linux/pinctrl/consumer.h> | ||||
| +#include <linux/pinctrl/machine.h> | ||||
| + | ||||
| +#include <asm/mach-ralink/ralink_regs.h> | ||||
| +#include <asm/mach-ralink/pinmux.h> | ||||
| +#include <asm/mach-ralink/mt7620.h> | ||||
| + | ||||
| +#include "core.h" | ||||
| + | ||||
| +#define SYSC_REG_GPIO_MODE	0x60 | ||||
| +#define SYSC_REG_GPIO_MODE2	0x64 | ||||
| + | ||||
| +struct rt2880_priv { | ||||
| +	struct device *dev; | ||||
| + | ||||
| +	struct pinctrl_pin_desc *pads; | ||||
| +	struct pinctrl_desc *desc; | ||||
| + | ||||
| +	struct rt2880_pmx_func **func; | ||||
| +	int func_count; | ||||
| + | ||||
| +	struct rt2880_pmx_group *groups; | ||||
| +	const char **group_names; | ||||
| +	int group_count; | ||||
| + | ||||
| +	uint8_t *gpio; | ||||
| +	int max_pins; | ||||
| +}; | ||||
| + | ||||
| +static int rt2880_get_group_count(struct pinctrl_dev *pctrldev) | ||||
| +{ | ||||
| +	struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); | ||||
| + | ||||
| +	return p->group_count; | ||||
| +} | ||||
| + | ||||
| +static const char *rt2880_get_group_name(struct pinctrl_dev *pctrldev, | ||||
| +					 unsigned group) | ||||
| +{ | ||||
| +	struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); | ||||
| + | ||||
| +	if (group >= p->group_count) | ||||
| +		return NULL; | ||||
| + | ||||
| +	return p->group_names[group]; | ||||
| +} | ||||
| + | ||||
| +static int rt2880_get_group_pins(struct pinctrl_dev *pctrldev, | ||||
| +				 unsigned group, | ||||
| +				 const unsigned **pins, | ||||
| +				 unsigned *num_pins) | ||||
| +{ | ||||
| +	struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); | ||||
| + | ||||
| +	if (group >= p->group_count) | ||||
| +		return -EINVAL; | ||||
| + | ||||
| +	*pins = p->groups[group].func[0].pins; | ||||
| +	*num_pins = p->groups[group].func[0].pin_count; | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static void rt2880_pinctrl_dt_free_map(struct pinctrl_dev *pctrldev, | ||||
| +				    struct pinctrl_map *map, unsigned num_maps) | ||||
| +{ | ||||
| +	int i; | ||||
| + | ||||
| +	for (i = 0; i < num_maps; i++) | ||||
| +		if (map[i].type == PIN_MAP_TYPE_CONFIGS_PIN || | ||||
| +		    map[i].type == PIN_MAP_TYPE_CONFIGS_GROUP) | ||||
| +			kfree(map[i].data.configs.configs); | ||||
| +	kfree(map); | ||||
| +} | ||||
| + | ||||
| +static void rt2880_pinctrl_pin_dbg_show(struct pinctrl_dev *pctrldev, | ||||
| +					struct seq_file *s, | ||||
| +					unsigned offset) | ||||
| +{ | ||||
| +	seq_printf(s, "ralink pio"); | ||||
| +} | ||||
| + | ||||
| +static void rt2880_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctrldev, | ||||
| +				struct device_node *np, | ||||
| +				struct pinctrl_map **map) | ||||
| +{ | ||||
| +        const char *function; | ||||
| +	int func = of_property_read_string(np, "ralink,function", &function); | ||||
| +	int grps = of_property_count_strings(np, "ralink,group"); | ||||
| +	int i; | ||||
| + | ||||
| +	if (func || !grps) | ||||
| +		return; | ||||
| + | ||||
| +	for (i = 0; i < grps; i++) { | ||||
| +	        const char *group; | ||||
| + | ||||
| +		of_property_read_string_index(np, "ralink,group", i, &group); | ||||
| + | ||||
| +		(*map)->type = PIN_MAP_TYPE_MUX_GROUP; | ||||
| +		(*map)->name = function; | ||||
| +		(*map)->data.mux.group = group; | ||||
| +		(*map)->data.mux.function = function; | ||||
| +		(*map)++; | ||||
| +	} | ||||
| +} | ||||
| + | ||||
| +static int rt2880_pinctrl_dt_node_to_map(struct pinctrl_dev *pctrldev, | ||||
| +				struct device_node *np_config, | ||||
| +				struct pinctrl_map **map, | ||||
| +				unsigned *num_maps) | ||||
| +{ | ||||
| +	int max_maps = 0; | ||||
| +	struct pinctrl_map *tmp; | ||||
| +	struct device_node *np; | ||||
| + | ||||
| +	for_each_child_of_node(np_config, np) { | ||||
| +		int ret = of_property_count_strings(np, "ralink,group"); | ||||
| + | ||||
| +		if (ret >= 0) | ||||
| +			max_maps += ret; | ||||
| +	} | ||||
| + | ||||
| +	if (!max_maps) | ||||
| +		return max_maps; | ||||
| + | ||||
| +	*map = kzalloc(max_maps * sizeof(struct pinctrl_map), GFP_KERNEL); | ||||
| +	if (!*map) | ||||
| +		return -ENOMEM; | ||||
| + | ||||
| +	tmp = *map; | ||||
| + | ||||
| +	for_each_child_of_node(np_config, np) | ||||
| +		rt2880_pinctrl_dt_subnode_to_map(pctrldev, np, &tmp); | ||||
| +	*num_maps = max_maps; | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static const struct pinctrl_ops rt2880_pctrl_ops = { | ||||
| +	.get_groups_count	= rt2880_get_group_count, | ||||
| +	.get_group_name		= rt2880_get_group_name, | ||||
| +	.get_group_pins		= rt2880_get_group_pins, | ||||
| +	.pin_dbg_show		= rt2880_pinctrl_pin_dbg_show, | ||||
| +	.dt_node_to_map		= rt2880_pinctrl_dt_node_to_map, | ||||
| +	.dt_free_map		= rt2880_pinctrl_dt_free_map, | ||||
| +}; | ||||
| + | ||||
| +static int rt2880_pmx_func_count(struct pinctrl_dev *pctrldev) | ||||
| +{ | ||||
| +	struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); | ||||
| + | ||||
| +	return p->func_count; | ||||
| +} | ||||
| + | ||||
| +static const char *rt2880_pmx_func_name(struct pinctrl_dev *pctrldev, | ||||
| +					 unsigned func) | ||||
| +{ | ||||
| +	struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); | ||||
| + | ||||
| +	return p->func[func]->name; | ||||
| +} | ||||
| + | ||||
| +static int rt2880_pmx_group_get_groups(struct pinctrl_dev *pctrldev, | ||||
| +				unsigned func, | ||||
| +				const char * const **groups, | ||||
| +				unsigned * const num_groups) | ||||
| +{ | ||||
| +	struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); | ||||
| + | ||||
| +	if (p->func[func]->group_count == 1) | ||||
| +		*groups = &p->group_names[p->func[func]->groups[0]]; | ||||
| +	else | ||||
| +		*groups = p->group_names; | ||||
| + | ||||
| +	*num_groups = p->func[func]->group_count; | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static int rt2880_pmx_group_enable(struct pinctrl_dev *pctrldev, | ||||
| +				unsigned func, | ||||
| +				unsigned group) | ||||
| +{ | ||||
| +	struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); | ||||
| +        u32 mode = 0; | ||||
| +	u32 reg = SYSC_REG_GPIO_MODE; | ||||
| +	int i; | ||||
| +	int shift; | ||||
| + | ||||
| +	/* dont allow double use */ | ||||
| +	if (p->groups[group].enabled) { | ||||
| +		dev_err(p->dev, "%s is already enabled\n", p->groups[group].name); | ||||
| +		return -EBUSY; | ||||
| +	} | ||||
| + | ||||
| +	p->groups[group].enabled = 1; | ||||
| +	p->func[func]->enabled = 1; | ||||
| + | ||||
| +	shift = p->groups[group].shift; | ||||
| +	if (shift >= 32) { | ||||
| +		shift -= 32; | ||||
| +		reg = SYSC_REG_GPIO_MODE2; | ||||
| +	} | ||||
| +	mode = rt_sysc_r32(reg); | ||||
| +	mode &= ~(p->groups[group].mask << shift); | ||||
| + | ||||
| +	/* mark the pins as gpio */ | ||||
| +	for (i = 0; i < p->groups[group].func[0].pin_count; i++) | ||||
| +		p->gpio[p->groups[group].func[0].pins[i]] = 1; | ||||
| + | ||||
| +	/* function 0 is gpio and needs special handling */ | ||||
| +	if (func == 0) { | ||||
| +		mode |= p->groups[group].gpio << shift; | ||||
| +	} else { | ||||
| +		for (i = 0; i < p->func[func]->pin_count; i++) | ||||
| +			p->gpio[p->func[func]->pins[i]] = 0; | ||||
| +		mode |= p->func[func]->value << shift; | ||||
| +	} | ||||
| +	rt_sysc_w32(mode, reg); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static int rt2880_pmx_group_gpio_request_enable(struct pinctrl_dev *pctrldev, | ||||
| +				struct pinctrl_gpio_range *range, | ||||
| +				unsigned pin) | ||||
| +{ | ||||
| +	struct rt2880_priv *p = pinctrl_dev_get_drvdata(pctrldev); | ||||
| + | ||||
| +	if (!p->gpio[pin]) { | ||||
| +		dev_err(p->dev, "pin %d is not set to gpio mux\n", pin); | ||||
| +		return -EINVAL; | ||||
| +	} | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static const struct pinmux_ops rt2880_pmx_group_ops = { | ||||
| +	.get_functions_count	= rt2880_pmx_func_count, | ||||
| +	.get_function_name	= rt2880_pmx_func_name, | ||||
| +	.get_function_groups	= rt2880_pmx_group_get_groups, | ||||
| +	.set_mux		= rt2880_pmx_group_enable, | ||||
| +	.gpio_request_enable	= rt2880_pmx_group_gpio_request_enable, | ||||
| +}; | ||||
| + | ||||
| +static struct pinctrl_desc rt2880_pctrl_desc = { | ||||
| +	.owner		= THIS_MODULE, | ||||
| +	.name		= "rt2880-pinmux", | ||||
| +	.pctlops	= &rt2880_pctrl_ops, | ||||
| +	.pmxops		= &rt2880_pmx_group_ops, | ||||
| +}; | ||||
| + | ||||
| +static struct rt2880_pmx_func gpio_func = { | ||||
| +	.name = "gpio", | ||||
| +}; | ||||
| + | ||||
| +static int rt2880_pinmux_index(struct rt2880_priv *p) | ||||
| +{ | ||||
| +	struct rt2880_pmx_func **f; | ||||
| +	struct rt2880_pmx_group *mux = p->groups; | ||||
| +	int i, j, c = 0; | ||||
| + | ||||
| +	/* count the mux functions */ | ||||
| +	while (mux->name) { | ||||
| +		p->group_count++; | ||||
| +		mux++; | ||||
| +	} | ||||
| + | ||||
| +	/* allocate the group names array needed by the gpio function */ | ||||
| +	p->group_names = devm_kzalloc(p->dev, sizeof(char *) * p->group_count, GFP_KERNEL); | ||||
| +	if (!p->group_names) | ||||
| +		return -1; | ||||
| + | ||||
| +	for (i = 0; i < p->group_count; i++) { | ||||
| +		p->group_names[i] = p->groups[i].name; | ||||
| +		p->func_count += p->groups[i].func_count; | ||||
| +	} | ||||
| + | ||||
| +	/* we have a dummy function[0] for gpio */ | ||||
| +	p->func_count++; | ||||
| + | ||||
| +	/* allocate our function and group mapping index buffers */ | ||||
| +	f = p->func = devm_kzalloc(p->dev, sizeof(struct rt2880_pmx_func) * p->func_count, GFP_KERNEL); | ||||
| +	gpio_func.groups = devm_kzalloc(p->dev, sizeof(int) * p->group_count, GFP_KERNEL); | ||||
| +	if (!f || !gpio_func.groups) | ||||
| +		return -1; | ||||
| + | ||||
| +	/* add a backpointer to the function so it knows its group */ | ||||
| +	gpio_func.group_count = p->group_count; | ||||
| +	for (i = 0; i < gpio_func.group_count; i++) | ||||
| +		gpio_func.groups[i] = i; | ||||
| + | ||||
| +	f[c] = &gpio_func; | ||||
| +	c++; | ||||
| + | ||||
| +	/* add remaining functions */ | ||||
| +	for (i = 0; i < p->group_count; i++) { | ||||
| +		for (j = 0; j < p->groups[i].func_count; j++) { | ||||
| +			f[c] = &p->groups[i].func[j]; | ||||
| +			f[c]->groups = devm_kzalloc(p->dev, sizeof(int), GFP_KERNEL); | ||||
| +			f[c]->groups[0] = i; | ||||
| +			f[c]->group_count = 1; | ||||
| +			c++; | ||||
| +		} | ||||
| +	} | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static int rt2880_pinmux_pins(struct rt2880_priv *p) | ||||
| +{ | ||||
| +	int i, j; | ||||
| + | ||||
| +	/* loop over the functions and initialize the pins array. also work out the highest pin used */ | ||||
| +	for (i = 0; i < p->func_count; i++) { | ||||
| +		int pin; | ||||
| + | ||||
| +		if (!p->func[i]->pin_count) | ||||
| +			continue; | ||||
| + | ||||
| +		p->func[i]->pins = devm_kzalloc(p->dev, sizeof(int) * p->func[i]->pin_count, GFP_KERNEL); | ||||
| +		for (j = 0; j < p->func[i]->pin_count; j++) | ||||
| +			p->func[i]->pins[j] = p->func[i]->pin_first + j; | ||||
| + | ||||
| +		pin = p->func[i]->pin_first + p->func[i]->pin_count; | ||||
| +		if (pin > p->max_pins) | ||||
| +			p->max_pins = pin; | ||||
| +	} | ||||
| + | ||||
| +	/* the buffer that tells us which pins are gpio */ | ||||
| +	p->gpio = devm_kzalloc(p->dev,sizeof(uint8_t) * p->max_pins, | ||||
| +		GFP_KERNEL); | ||||
| +	/* the pads needed to tell pinctrl about our pins */ | ||||
| +	p->pads = devm_kzalloc(p->dev, | ||||
| +		sizeof(struct pinctrl_pin_desc) * p->max_pins, | ||||
| +		GFP_KERNEL); | ||||
| +	if (!p->pads || !p->gpio ) { | ||||
| +		dev_err(p->dev, "Failed to allocate gpio data\n"); | ||||
| +		return -ENOMEM; | ||||
| +	} | ||||
| + | ||||
| +	memset(p->gpio, 1, sizeof(uint8_t) * p->max_pins); | ||||
| +	for (i = 0; i < p->func_count; i++) { | ||||
| +		if (!p->func[i]->pin_count) | ||||
| +			continue; | ||||
| + | ||||
| +		for (j = 0; j < p->func[i]->pin_count; j++) | ||||
| +			p->gpio[p->func[i]->pins[j]] = 0; | ||||
| +	} | ||||
| + | ||||
| +	/* pin 0 is always a gpio */ | ||||
| +	p->gpio[0] = 1; | ||||
| + | ||||
| +	/* set the pads */ | ||||
| +	for (i = 0; i < p->max_pins; i++) { | ||||
| +		/* strlen("ioXY") + 1 = 5 */ | ||||
| +		char *name = devm_kzalloc(p->dev, 5, GFP_KERNEL); | ||||
| + | ||||
| +		if (!name) { | ||||
| +			dev_err(p->dev, "Failed to allocate pad name\n"); | ||||
| +			return -ENOMEM; | ||||
| +		} | ||||
| +		snprintf(name, 5, "io%d", i); | ||||
| +		p->pads[i].number = i; | ||||
| +		p->pads[i].name = name; | ||||
| +	} | ||||
| +	p->desc->pins = p->pads; | ||||
| +	p->desc->npins = p->max_pins; | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static int rt2880_pinmux_probe(struct platform_device *pdev) | ||||
| +{ | ||||
| +	struct rt2880_priv *p; | ||||
| +	struct pinctrl_dev *dev; | ||||
| +	struct device_node *np; | ||||
| + | ||||
| +	if (!rt2880_pinmux_data) | ||||
| +		return -ENOSYS; | ||||
| + | ||||
| +	/* setup the private data */ | ||||
| +	p = devm_kzalloc(&pdev->dev, sizeof(struct rt2880_priv), GFP_KERNEL); | ||||
| +	if (!p) | ||||
| +		return -ENOMEM; | ||||
| + | ||||
| +	p->dev = &pdev->dev; | ||||
| +	p->desc = &rt2880_pctrl_desc; | ||||
| +	p->groups = rt2880_pinmux_data; | ||||
| +	platform_set_drvdata(pdev, p); | ||||
| + | ||||
| +	/* init the device */ | ||||
| +	if (rt2880_pinmux_index(p)) { | ||||
| +		dev_err(&pdev->dev, "failed to load index\n"); | ||||
| +		return -EINVAL; | ||||
| +	} | ||||
| +	if (rt2880_pinmux_pins(p)) { | ||||
| +		dev_err(&pdev->dev, "failed to load pins\n"); | ||||
| +		return -EINVAL; | ||||
| +	} | ||||
| +	dev = pinctrl_register(p->desc, &pdev->dev, p); | ||||
| +	if (IS_ERR(dev)) | ||||
| +		return PTR_ERR(dev); | ||||
| + | ||||
| +	/* finalize by adding gpio ranges for enables gpio controllers */ | ||||
| +	for_each_compatible_node(np, NULL, "ralink,rt2880-gpio") { | ||||
| +		const __be32 *ngpio, *gpiobase; | ||||
| +		struct pinctrl_gpio_range *range; | ||||
| +		char *name; | ||||
| + | ||||
| +		if (!of_device_is_available(np)) | ||||
| +			continue; | ||||
| + | ||||
| +		ngpio = of_get_property(np, "ralink,num-gpios", NULL); | ||||
| +		gpiobase = of_get_property(np, "ralink,gpio-base", NULL); | ||||
| +		if (!ngpio || !gpiobase) { | ||||
| +			dev_err(&pdev->dev, "failed to load chip info\n"); | ||||
| +			return -EINVAL; | ||||
| +		} | ||||
| + | ||||
| +		range = devm_kzalloc(p->dev, sizeof(struct pinctrl_gpio_range) + 4, GFP_KERNEL); | ||||
| +		range->name = name = (char *) &range[1]; | ||||
| +		sprintf(name, "pio"); | ||||
| +		range->npins = __be32_to_cpu(*ngpio); | ||||
| +		range->base = __be32_to_cpu(*gpiobase); | ||||
| +		range->pin_base = range->base; | ||||
| +		pinctrl_add_gpio_range(dev, range); | ||||
| +	} | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static const struct of_device_id rt2880_pinmux_match[] = { | ||||
| +	{ .compatible = "ralink,rt2880-pinmux" }, | ||||
| +	{}, | ||||
| +}; | ||||
| +MODULE_DEVICE_TABLE(of, rt2880_pinmux_match); | ||||
| + | ||||
| +static struct platform_driver rt2880_pinmux_driver = { | ||||
| +	.probe = rt2880_pinmux_probe, | ||||
| +	.driver = { | ||||
| +		.name = "rt2880-pinmux", | ||||
| +		.owner = THIS_MODULE, | ||||
| +		.of_match_table = rt2880_pinmux_match, | ||||
| +	}, | ||||
| +}; | ||||
| + | ||||
| +int __init rt2880_pinmux_init(void) | ||||
| +{ | ||||
| +	return platform_driver_register(&rt2880_pinmux_driver); | ||||
| +} | ||||
| + | ||||
| +core_initcall_sync(rt2880_pinmux_init); | ||||
| @@ -0,0 +1,59 @@ | ||||
| From d410e5478c622c01fcf31427533df5f433df9146 Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <blogic@openwrt.org> | ||||
| Date: Sun, 28 Jul 2013 19:45:30 +0200 | ||||
| Subject: [PATCH 26/53] DT: Add documentation for gpio-ralink | ||||
|  | ||||
| Describe gpio-ralink binding. | ||||
|  | ||||
| Signed-off-by: John Crispin <blogic@openwrt.org> | ||||
| Cc: linux-mips@linux-mips.org | ||||
| Cc: devicetree@vger.kernel.org | ||||
| Cc: linux-gpio@vger.kernel.org | ||||
| --- | ||||
|  .../devicetree/bindings/gpio/gpio-ralink.txt       |   40 ++++++++++++++++++++ | ||||
|  1 file changed, 40 insertions(+) | ||||
|  create mode 100644 Documentation/devicetree/bindings/gpio/gpio-ralink.txt | ||||
|  | ||||
| --- /dev/null | ||||
| +++ b/Documentation/devicetree/bindings/gpio/gpio-ralink.txt | ||||
| @@ -0,0 +1,40 @@ | ||||
| +Ralink SoC GPIO controller bindings | ||||
| + | ||||
| +Required properties: | ||||
| +- compatible: | ||||
| +  - "ralink,rt2880-gpio" for Ralink controllers | ||||
| +- #gpio-cells : Should be two. | ||||
| +  - first cell is the pin number | ||||
| +  - second cell is used to specify optional parameters (unused) | ||||
| +- gpio-controller : Marks the device node as a GPIO controller | ||||
| +- reg : Physical base address and length of the controller's registers | ||||
| +- interrupt-parent: phandle to the INTC device node | ||||
| +- interrupts : Specify the INTC interrupt number | ||||
| +- ralink,num-gpios : Specify the number of GPIOs | ||||
| +- ralink,register-map : The register layout depends on the GPIO bank and actual | ||||
| +		SoC type. Register offsets need to be in this order. | ||||
| +		[ INT, EDGE, RENA, FENA, DATA, DIR, POL, SET, RESET, TOGGLE ] | ||||
| + | ||||
| +Optional properties: | ||||
| +- ralink,gpio-base : Specify the GPIO chips base number | ||||
| + | ||||
| +Example: | ||||
| + | ||||
| +	gpio0: gpio@600 { | ||||
| +		compatible = "ralink,rt5350-gpio", "ralink,rt2880-gpio"; | ||||
| + | ||||
| +		#gpio-cells = <2>; | ||||
| +		gpio-controller; | ||||
| + | ||||
| +		reg = <0x600 0x34>; | ||||
| + | ||||
| +		interrupt-parent = <&intc>; | ||||
| +		interrupts = <6>; | ||||
| + | ||||
| +		ralink,gpio-base = <0>; | ||||
| +		ralink,num-gpios = <24>; | ||||
| +		ralink,register-map = [ 00 04 08 0c | ||||
| +				20 24 28 2c | ||||
| +				30 34 ]; | ||||
| + | ||||
| +	}; | ||||
| @@ -0,0 +1,430 @@ | ||||
| From 69fdd2c4f937796b934e89c33acde9d082e27bfd Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <blogic@openwrt.org> | ||||
| Date: Mon, 4 Aug 2014 20:36:29 +0200 | ||||
| Subject: [PATCH 27/53] GPIO: MIPS: ralink: add gpio driver for ralink SoC | ||||
|  | ||||
| Add gpio driver for Ralink SoC. This driver makes the gpio core on | ||||
| RT2880, RT305x, rt3352, rt3662, rt3883, rt5350 and mt7620 work. | ||||
|  | ||||
| Signed-off-by: John Crispin <blogic@openwrt.org> | ||||
| Cc: linux-mips@linux-mips.org | ||||
| Cc: linux-gpio@vger.kernel.org | ||||
| --- | ||||
|  arch/mips/include/asm/mach-ralink/gpio.h |   24 ++ | ||||
|  drivers/gpio/Kconfig                     |    6 + | ||||
|  drivers/gpio/Makefile                    |    1 + | ||||
|  drivers/gpio/gpio-ralink.c               |  355 ++++++++++++++++++++++++++++++ | ||||
|  4 files changed, 386 insertions(+) | ||||
|  create mode 100644 arch/mips/include/asm/mach-ralink/gpio.h | ||||
|  create mode 100644 drivers/gpio/gpio-ralink.c | ||||
|  | ||||
| --- /dev/null | ||||
| +++ b/arch/mips/include/asm/mach-ralink/gpio.h | ||||
| @@ -0,0 +1,24 @@ | ||||
| +/* | ||||
| + *  Ralink SoC GPIO API support | ||||
| + * | ||||
| + *  Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> | ||||
| + *  Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> | ||||
| + * | ||||
| + *  This program is free software; you can redistribute it and/or modify it | ||||
| + *  under the terms of the GNU General Public License version 2 as published | ||||
| + *  by the Free Software Foundation. | ||||
| + * | ||||
| + */ | ||||
| + | ||||
| +#ifndef __ASM_MACH_RALINK_GPIO_H | ||||
| +#define __ASM_MACH_RALINK_GPIO_H | ||||
| + | ||||
| +#define ARCH_NR_GPIOS	128 | ||||
| +#include <asm-generic/gpio.h> | ||||
| + | ||||
| +#define gpio_get_value	__gpio_get_value | ||||
| +#define gpio_set_value	__gpio_set_value | ||||
| +#define gpio_cansleep	__gpio_cansleep | ||||
| +#define gpio_to_irq	__gpio_to_irq | ||||
| + | ||||
| +#endif /* __ASM_MACH_RALINK_GPIO_H */ | ||||
| --- a/drivers/gpio/Kconfig | ||||
| +++ b/drivers/gpio/Kconfig | ||||
| @@ -369,6 +369,12 @@ config GPIO_RCAR | ||||
|  	help | ||||
|  	  Say yes here to support GPIO on Renesas R-Car SoCs. | ||||
|   | ||||
| +config GPIO_RALINK | ||||
| +	bool "Ralink GPIO Support" | ||||
| +	depends on RALINK | ||||
| +	help | ||||
| +	  Say yes here to support the Ralink SoC GPIO device | ||||
| + | ||||
|  config GPIO_SPEAR_SPICS | ||||
|  	bool "ST SPEAr13xx SPI Chip Select as GPIO support" | ||||
|  	depends on PLAT_SPEAR | ||||
| --- a/drivers/gpio/Makefile | ||||
| +++ b/drivers/gpio/Makefile | ||||
| @@ -91,6 +91,7 @@ obj-$(CONFIG_GPIO_PCH)		+= gpio-pch.o | ||||
|  obj-$(CONFIG_GPIO_PISOSR)	+= gpio-pisosr.o | ||||
|  obj-$(CONFIG_GPIO_PL061)	+= gpio-pl061.o | ||||
|  obj-$(CONFIG_GPIO_PXA)		+= gpio-pxa.o | ||||
| +obj-$(CONFIG_GPIO_RALINK)	+= gpio-ralink.o | ||||
|  obj-$(CONFIG_GPIO_RC5T583)	+= gpio-rc5t583.o | ||||
|  obj-$(CONFIG_GPIO_RDC321X)	+= gpio-rdc321x.o | ||||
|  obj-$(CONFIG_GPIO_RCAR)		+= gpio-rcar.o | ||||
| --- /dev/null | ||||
| +++ b/drivers/gpio/gpio-ralink.c | ||||
| @@ -0,0 +1,355 @@ | ||||
| +/* | ||||
| + * This program is free software; you can redistribute it and/or modify it | ||||
| + * under the terms of the GNU General Public License version 2 as published | ||||
| + * by the Free Software Foundation. | ||||
| + * | ||||
| + * Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org> | ||||
| + * Copyright (C) 2013 John Crispin <blogic@openwrt.org> | ||||
| + */ | ||||
| + | ||||
| +#include <linux/module.h> | ||||
| +#include <linux/io.h> | ||||
| +#include <linux/gpio.h> | ||||
| +#include <linux/spinlock.h> | ||||
| +#include <linux/platform_device.h> | ||||
| +#include <linux/of_irq.h> | ||||
| +#include <linux/irqdomain.h> | ||||
| +#include <linux/interrupt.h> | ||||
| + | ||||
| +enum ralink_gpio_reg { | ||||
| +	GPIO_REG_INT = 0, | ||||
| +	GPIO_REG_EDGE, | ||||
| +	GPIO_REG_RENA, | ||||
| +	GPIO_REG_FENA, | ||||
| +	GPIO_REG_DATA, | ||||
| +	GPIO_REG_DIR, | ||||
| +	GPIO_REG_POL, | ||||
| +	GPIO_REG_SET, | ||||
| +	GPIO_REG_RESET, | ||||
| +	GPIO_REG_TOGGLE, | ||||
| +	GPIO_REG_MAX | ||||
| +}; | ||||
| + | ||||
| +struct ralink_gpio_chip { | ||||
| +	struct gpio_chip chip; | ||||
| +	u8 regs[GPIO_REG_MAX]; | ||||
| + | ||||
| +	spinlock_t lock; | ||||
| +	void __iomem *membase; | ||||
| +	struct irq_domain *domain; | ||||
| +	int irq; | ||||
| + | ||||
| +	u32 rising; | ||||
| +	u32 falling; | ||||
| +}; | ||||
| + | ||||
| +#define MAP_MAX	4 | ||||
| +static struct irq_domain *irq_map[MAP_MAX]; | ||||
| +static int irq_map_count; | ||||
| +static atomic_t irq_refcount = ATOMIC_INIT(0); | ||||
| + | ||||
| +static inline struct ralink_gpio_chip *to_ralink_gpio(struct gpio_chip *chip) | ||||
| +{ | ||||
| +	struct ralink_gpio_chip *rg; | ||||
| + | ||||
| +	rg = container_of(chip, struct ralink_gpio_chip, chip); | ||||
| + | ||||
| +	return rg; | ||||
| +} | ||||
| + | ||||
| +static inline void rt_gpio_w32(struct ralink_gpio_chip *rg, u8 reg, u32 val) | ||||
| +{ | ||||
| +	iowrite32(val, rg->membase + rg->regs[reg]); | ||||
| +} | ||||
| + | ||||
| +static inline u32 rt_gpio_r32(struct ralink_gpio_chip *rg, u8 reg) | ||||
| +{ | ||||
| +	return ioread32(rg->membase + rg->regs[reg]); | ||||
| +} | ||||
| + | ||||
| +static void ralink_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | ||||
| +{ | ||||
| +	struct ralink_gpio_chip *rg = to_ralink_gpio(chip); | ||||
| + | ||||
| +	rt_gpio_w32(rg, (value) ? GPIO_REG_SET : GPIO_REG_RESET, BIT(offset)); | ||||
| +} | ||||
| + | ||||
| +static int ralink_gpio_get(struct gpio_chip *chip, unsigned offset) | ||||
| +{ | ||||
| +	struct ralink_gpio_chip *rg = to_ralink_gpio(chip); | ||||
| + | ||||
| +	return !!(rt_gpio_r32(rg, GPIO_REG_DATA) & BIT(offset)); | ||||
| +} | ||||
| + | ||||
| +static int ralink_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | ||||
| +{ | ||||
| +	struct ralink_gpio_chip *rg = to_ralink_gpio(chip); | ||||
| +	unsigned long flags; | ||||
| +	u32 t; | ||||
| + | ||||
| +	spin_lock_irqsave(&rg->lock, flags); | ||||
| +	t = rt_gpio_r32(rg, GPIO_REG_DIR); | ||||
| +	t &= ~BIT(offset); | ||||
| +	rt_gpio_w32(rg, GPIO_REG_DIR, t); | ||||
| +	spin_unlock_irqrestore(&rg->lock, flags); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static int ralink_gpio_direction_output(struct gpio_chip *chip, | ||||
| +					unsigned offset, int value) | ||||
| +{ | ||||
| +	struct ralink_gpio_chip *rg = to_ralink_gpio(chip); | ||||
| +	unsigned long flags; | ||||
| +	u32 t; | ||||
| + | ||||
| +	spin_lock_irqsave(&rg->lock, flags); | ||||
| +	ralink_gpio_set(chip, offset, value); | ||||
| +	t = rt_gpio_r32(rg, GPIO_REG_DIR); | ||||
| +	t |= BIT(offset); | ||||
| +	rt_gpio_w32(rg, GPIO_REG_DIR, t); | ||||
| +	spin_unlock_irqrestore(&rg->lock, flags); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static int ralink_gpio_to_irq(struct gpio_chip *chip, unsigned pin) | ||||
| +{ | ||||
| +	struct ralink_gpio_chip *rg = to_ralink_gpio(chip); | ||||
| + | ||||
| +	if (rg->irq < 1) | ||||
| +		return -1; | ||||
| + | ||||
| +	return irq_create_mapping(rg->domain, pin); | ||||
| +} | ||||
| + | ||||
| +static void ralink_gpio_irq_handler(struct irq_desc *desc) | ||||
| +{ | ||||
| +	int i; | ||||
| + | ||||
| +	for (i = 0; i < irq_map_count; i++) { | ||||
| +		struct irq_domain *domain = irq_map[i]; | ||||
| +		struct ralink_gpio_chip *rg; | ||||
| +		unsigned long pending; | ||||
| +		int bit; | ||||
| + | ||||
| +		rg = (struct ralink_gpio_chip *) domain->host_data; | ||||
| +		pending = rt_gpio_r32(rg, GPIO_REG_INT); | ||||
| + | ||||
| +		for_each_set_bit(bit, &pending, rg->chip.ngpio) { | ||||
| +			u32 map = irq_find_mapping(domain, bit); | ||||
| +			generic_handle_irq(map); | ||||
| +			rt_gpio_w32(rg, GPIO_REG_INT, BIT(bit)); | ||||
| +		} | ||||
| +	} | ||||
| +} | ||||
| + | ||||
| +static void ralink_gpio_irq_unmask(struct irq_data *d) | ||||
| +{ | ||||
| +	struct ralink_gpio_chip *rg; | ||||
| +	unsigned long flags; | ||||
| +	u32 rise, fall; | ||||
| + | ||||
| +	rg = (struct ralink_gpio_chip *) d->domain->host_data; | ||||
| +	rise = rt_gpio_r32(rg, GPIO_REG_RENA); | ||||
| +	fall = rt_gpio_r32(rg, GPIO_REG_FENA); | ||||
| + | ||||
| +	spin_lock_irqsave(&rg->lock, flags); | ||||
| +	rt_gpio_w32(rg, GPIO_REG_RENA, rise | (BIT(d->hwirq) & rg->rising)); | ||||
| +	rt_gpio_w32(rg, GPIO_REG_FENA, fall | (BIT(d->hwirq) & rg->falling)); | ||||
| +	spin_unlock_irqrestore(&rg->lock, flags); | ||||
| +} | ||||
| + | ||||
| +static void ralink_gpio_irq_mask(struct irq_data *d) | ||||
| +{ | ||||
| +	struct ralink_gpio_chip *rg; | ||||
| +	unsigned long flags; | ||||
| +	u32 rise, fall; | ||||
| + | ||||
| +	rg = (struct ralink_gpio_chip *) d->domain->host_data; | ||||
| +	rise = rt_gpio_r32(rg, GPIO_REG_RENA); | ||||
| +	fall = rt_gpio_r32(rg, GPIO_REG_FENA); | ||||
| + | ||||
| +	spin_lock_irqsave(&rg->lock, flags); | ||||
| +	rt_gpio_w32(rg, GPIO_REG_FENA, fall & ~BIT(d->hwirq)); | ||||
| +	rt_gpio_w32(rg, GPIO_REG_RENA, rise & ~BIT(d->hwirq)); | ||||
| +	spin_unlock_irqrestore(&rg->lock, flags); | ||||
| +} | ||||
| + | ||||
| +static int ralink_gpio_irq_type(struct irq_data *d, unsigned int type) | ||||
| +{ | ||||
| +	struct ralink_gpio_chip *rg; | ||||
| +	u32 mask = BIT(d->hwirq); | ||||
| + | ||||
| +	rg = (struct ralink_gpio_chip *) d->domain->host_data; | ||||
| + | ||||
| +	if (type == IRQ_TYPE_PROBE) { | ||||
| +		if ((rg->rising | rg->falling) & mask) | ||||
| +			return 0; | ||||
| + | ||||
| +		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; | ||||
| +	} | ||||
| + | ||||
| +	if (type & IRQ_TYPE_EDGE_RISING) | ||||
| +		rg->rising |= mask; | ||||
| +	else | ||||
| +		rg->rising &= ~mask; | ||||
| + | ||||
| +	if (type & IRQ_TYPE_EDGE_FALLING) | ||||
| +		rg->falling |= mask; | ||||
| +	else | ||||
| +		rg->falling &= ~mask; | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static struct irq_chip ralink_gpio_irq_chip = { | ||||
| +	.name		= "GPIO", | ||||
| +	.irq_unmask	= ralink_gpio_irq_unmask, | ||||
| +	.irq_mask	= ralink_gpio_irq_mask, | ||||
| +	.irq_mask_ack	= ralink_gpio_irq_mask, | ||||
| +	.irq_set_type	= ralink_gpio_irq_type, | ||||
| +}; | ||||
| + | ||||
| +static int gpio_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) | ||||
| +{ | ||||
| +	irq_set_chip_and_handler(irq, &ralink_gpio_irq_chip, handle_level_irq); | ||||
| +	irq_set_handler_data(irq, d); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static const struct irq_domain_ops irq_domain_ops = { | ||||
| +	.xlate = irq_domain_xlate_onecell, | ||||
| +	.map = gpio_map, | ||||
| +}; | ||||
| + | ||||
| +static void ralink_gpio_irq_init(struct device_node *np, | ||||
| +				 struct ralink_gpio_chip *rg) | ||||
| +{ | ||||
| +	if (irq_map_count >= MAP_MAX) | ||||
| +		return; | ||||
| + | ||||
| +	rg->irq = irq_of_parse_and_map(np, 0); | ||||
| +	if (!rg->irq) | ||||
| +		return; | ||||
| + | ||||
| +	rg->domain = irq_domain_add_linear(np, rg->chip.ngpio, | ||||
| +					   &irq_domain_ops, rg); | ||||
| +	if (!rg->domain) { | ||||
| +		dev_err(rg->chip.parent, "irq_domain_add_linear failed\n"); | ||||
| +		return; | ||||
| +	} | ||||
| + | ||||
| +	irq_map[irq_map_count++] = rg->domain; | ||||
| + | ||||
| +	rt_gpio_w32(rg, GPIO_REG_RENA, 0x0); | ||||
| +	rt_gpio_w32(rg, GPIO_REG_FENA, 0x0); | ||||
| + | ||||
| +	if (!atomic_read(&irq_refcount)) | ||||
| +		irq_set_chained_handler(rg->irq, ralink_gpio_irq_handler); | ||||
| +	atomic_inc(&irq_refcount); | ||||
| + | ||||
| +	dev_info(rg->chip.parent, "registering %d irq handlers\n", rg->chip.ngpio); | ||||
| +} | ||||
| + | ||||
| +static int ralink_gpio_request(struct gpio_chip *chip, unsigned offset) | ||||
| +{ | ||||
| +	int gpio = chip->base + offset; | ||||
| + | ||||
| +	return pinctrl_request_gpio(gpio); | ||||
| +} | ||||
| + | ||||
| +static void ralink_gpio_free(struct gpio_chip *chip, unsigned offset) | ||||
| +{ | ||||
| +	int gpio = chip->base + offset; | ||||
| + | ||||
| +	pinctrl_free_gpio(gpio); | ||||
| +} | ||||
| + | ||||
| +static int ralink_gpio_probe(struct platform_device *pdev) | ||||
| +{ | ||||
| +	struct device_node *np = pdev->dev.of_node; | ||||
| +	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||||
| +	struct ralink_gpio_chip *rg; | ||||
| +	const __be32 *ngpio, *gpiobase; | ||||
| + | ||||
| +	if (!res) { | ||||
| +		dev_err(&pdev->dev, "failed to find resource\n"); | ||||
| +		return -ENOMEM; | ||||
| +	} | ||||
| + | ||||
| +	rg = devm_kzalloc(&pdev->dev, | ||||
| +			sizeof(struct ralink_gpio_chip), GFP_KERNEL); | ||||
| +	if (!rg) | ||||
| +		return -ENOMEM; | ||||
| + | ||||
| +	rg->membase = devm_ioremap_resource(&pdev->dev, res); | ||||
| +	if (!rg->membase) { | ||||
| +		dev_err(&pdev->dev, "cannot remap I/O memory region\n"); | ||||
| +		return -ENOMEM; | ||||
| +	} | ||||
| + | ||||
| +	if (of_property_read_u8_array(np, "ralink,register-map", | ||||
| +			rg->regs, GPIO_REG_MAX)) { | ||||
| +		dev_err(&pdev->dev, "failed to read register definition\n"); | ||||
| +		return -EINVAL; | ||||
| +	} | ||||
| + | ||||
| +	ngpio = of_get_property(np, "ralink,num-gpios", NULL); | ||||
| +	if (!ngpio) { | ||||
| +		dev_err(&pdev->dev, "failed to read number of pins\n"); | ||||
| +		return -EINVAL; | ||||
| +	} | ||||
| + | ||||
| +	gpiobase = of_get_property(np, "ralink,gpio-base", NULL); | ||||
| +	if (gpiobase) | ||||
| +		rg->chip.base = be32_to_cpu(*gpiobase); | ||||
| +	else | ||||
| +		rg->chip.base = -1; | ||||
| + | ||||
| +	spin_lock_init(&rg->lock); | ||||
| + | ||||
| +	rg->chip.parent = &pdev->dev; | ||||
| +	rg->chip.label = dev_name(&pdev->dev); | ||||
| +	rg->chip.of_node = np; | ||||
| +	rg->chip.ngpio = be32_to_cpu(*ngpio); | ||||
| +	rg->chip.direction_input = ralink_gpio_direction_input; | ||||
| +	rg->chip.direction_output = ralink_gpio_direction_output; | ||||
| +	rg->chip.get = ralink_gpio_get; | ||||
| +	rg->chip.set = ralink_gpio_set; | ||||
| +	rg->chip.request = ralink_gpio_request; | ||||
| +	rg->chip.to_irq = ralink_gpio_to_irq; | ||||
| +	rg->chip.free = ralink_gpio_free; | ||||
| + | ||||
| +	/* set polarity to low for all lines */ | ||||
| +	rt_gpio_w32(rg, GPIO_REG_POL, 0); | ||||
| + | ||||
| +	dev_info(&pdev->dev, "registering %d gpios\n", rg->chip.ngpio); | ||||
| + | ||||
| +	ralink_gpio_irq_init(np, rg); | ||||
| + | ||||
| +	return gpiochip_add(&rg->chip); | ||||
| +} | ||||
| + | ||||
| +static const struct of_device_id ralink_gpio_match[] = { | ||||
| +	{ .compatible = "ralink,rt2880-gpio" }, | ||||
| +	{}, | ||||
| +}; | ||||
| +MODULE_DEVICE_TABLE(of, ralink_gpio_match); | ||||
| + | ||||
| +static struct platform_driver ralink_gpio_driver = { | ||||
| +	.probe = ralink_gpio_probe, | ||||
| +	.driver = { | ||||
| +		.name = "rt2880_gpio", | ||||
| +		.owner = THIS_MODULE, | ||||
| +		.of_match_table = ralink_gpio_match, | ||||
| +	}, | ||||
| +}; | ||||
| + | ||||
| +static int __init ralink_gpio_init(void) | ||||
| +{ | ||||
| +	return platform_driver_register(&ralink_gpio_driver); | ||||
| +} | ||||
| + | ||||
| +subsys_initcall(ralink_gpio_init); | ||||
| @@ -0,0 +1,405 @@ | ||||
| From 61ac7d9b4228de8c332900902c2b93189b042eab Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <blogic@openwrt.org> | ||||
| Date: Sun, 27 Jul 2014 11:00:32 +0100 | ||||
| Subject: [PATCH 28/53] GPIO: ralink: add mt7621 gpio controller | ||||
|  | ||||
| Signed-off-by: John Crispin <blogic@openwrt.org> | ||||
| --- | ||||
|  arch/mips/Kconfig          |    3 + | ||||
|  drivers/gpio/Kconfig       |    6 + | ||||
|  drivers/gpio/Makefile      |    1 + | ||||
|  drivers/gpio/gpio-mt7621.c |  354 ++++++++++++++++++++++++++++++++++++++++++++ | ||||
|  4 files changed, 364 insertions(+) | ||||
|  create mode 100644 drivers/gpio/gpio-mt7621.c | ||||
|  | ||||
| --- a/arch/mips/Kconfig | ||||
| +++ b/arch/mips/Kconfig | ||||
| @@ -619,6 +619,9 @@ config RALINK | ||||
|  	select RESET_CONTROLLER | ||||
|  	select PINCTRL | ||||
|  	select PINCTRL_RT2880 | ||||
| +	select ARCH_HAS_RESET_CONTROLLER | ||||
| +	select RESET_CONTROLLER | ||||
| +	select ARCH_REQUIRE_GPIOLIB | ||||
|   | ||||
|  config SGI_IP22 | ||||
|  	bool "SGI IP22 (Indy/Indigo2)" | ||||
| --- a/drivers/gpio/Kconfig | ||||
| +++ b/drivers/gpio/Kconfig | ||||
| @@ -270,6 +270,12 @@ config GPIO_MENZ127 | ||||
|  	help | ||||
|  	 Say yes here to support the MEN 16Z127 GPIO Controller | ||||
|   | ||||
| +config GPIO_MT7621 | ||||
| +	bool "Mediatek GPIO Support" | ||||
| +	depends on SOC_MT7620 || SOC_MT7621 | ||||
| +	help | ||||
| +	  Say yes here to support the Mediatek SoC GPIO device | ||||
| + | ||||
|  config GPIO_MM_LANTIQ | ||||
|  	bool "Lantiq Memory mapped GPIOs" | ||||
|  	depends on LANTIQ && SOC_XWAY | ||||
| --- a/drivers/gpio/Makefile | ||||
| +++ b/drivers/gpio/Makefile | ||||
| @@ -142,3 +142,4 @@ obj-$(CONFIG_GPIO_ZEVIO)	+= gpio-zevio.o | ||||
|  obj-$(CONFIG_GPIO_ZYNQ)		+= gpio-zynq.o | ||||
|  obj-$(CONFIG_GPIO_ZX)		+= gpio-zx.o | ||||
|  obj-$(CONFIG_GPIO_LOONGSON1)	+= gpio-loongson1.o | ||||
| +obj-$(CONFIG_GPIO_MT7621)	+= gpio-mt7621.o | ||||
| --- /dev/null | ||||
| +++ b/drivers/gpio/gpio-mt7621.c | ||||
| @@ -0,0 +1,354 @@ | ||||
| +/* | ||||
| + * This program is free software; you can redistribute it and/or modify it | ||||
| + * under the terms of the GNU General Public License version 2 as published | ||||
| + * by the Free Software Foundation. | ||||
| + * | ||||
| + * Copyright (C) 2009-2011 Gabor Juhos <juhosg@openwrt.org> | ||||
| + * Copyright (C) 2013 John Crispin <blogic@openwrt.org> | ||||
| + */ | ||||
| + | ||||
| +#include <linux/io.h> | ||||
| +#include <linux/err.h> | ||||
| +#include <linux/gpio.h> | ||||
| +#include <linux/module.h> | ||||
| +#include <linux/of_irq.h> | ||||
| +#include <linux/spinlock.h> | ||||
| +#include <linux/irqdomain.h> | ||||
| +#include <linux/interrupt.h> | ||||
| +#include <linux/platform_device.h> | ||||
| + | ||||
| +#define MTK_MAX_BANK		3 | ||||
| +#define MTK_BANK_WIDTH		32 | ||||
| + | ||||
| +enum mediatek_gpio_reg { | ||||
| +	GPIO_REG_CTRL = 0, | ||||
| +	GPIO_REG_POL, | ||||
| +	GPIO_REG_DATA, | ||||
| +	GPIO_REG_DSET, | ||||
| +	GPIO_REG_DCLR, | ||||
| +	GPIO_REG_REDGE, | ||||
| +	GPIO_REG_FEDGE, | ||||
| +	GPIO_REG_HLVL, | ||||
| +	GPIO_REG_LLVL, | ||||
| +	GPIO_REG_STAT, | ||||
| +	GPIO_REG_EDGE, | ||||
| +}; | ||||
| + | ||||
| +static void __iomem *mediatek_gpio_membase; | ||||
| +static int mediatek_gpio_irq; | ||||
| +static struct irq_domain *mediatek_gpio_irq_domain; | ||||
| +static atomic_t irq_refcount = ATOMIC_INIT(0); | ||||
| + | ||||
| +struct mtk_gc { | ||||
| +	struct gpio_chip chip; | ||||
| +	spinlock_t lock; | ||||
| +	int bank; | ||||
| +	u32 rising; | ||||
| +	u32 falling; | ||||
| +} *gc_map[MTK_MAX_BANK]; | ||||
| + | ||||
| +static inline struct mtk_gc | ||||
| +*to_mediatek_gpio(struct gpio_chip *chip) | ||||
| +{ | ||||
| +	struct mtk_gc *mgc; | ||||
| + | ||||
| +	mgc = container_of(chip, struct mtk_gc, chip); | ||||
| + | ||||
| +	return mgc; | ||||
| +} | ||||
| + | ||||
| +static inline void | ||||
| +mtk_gpio_w32(struct mtk_gc *rg, u8 reg, u32 val) | ||||
| +{ | ||||
| +	iowrite32(val, mediatek_gpio_membase + (reg * 0x10) + (rg->bank * 0x4)); | ||||
| +} | ||||
| + | ||||
| +static inline u32 | ||||
| +mtk_gpio_r32(struct mtk_gc *rg, u8 reg) | ||||
| +{ | ||||
| +	return ioread32(mediatek_gpio_membase + (reg * 0x10) + (rg->bank * 0x4)); | ||||
| +} | ||||
| + | ||||
| +static void | ||||
| +mediatek_gpio_set(struct gpio_chip *chip, unsigned offset, int value) | ||||
| +{ | ||||
| +	struct mtk_gc *rg = to_mediatek_gpio(chip); | ||||
| + | ||||
| +	mtk_gpio_w32(rg, (value) ? GPIO_REG_DSET : GPIO_REG_DCLR, BIT(offset)); | ||||
| +} | ||||
| + | ||||
| +static int | ||||
| +mediatek_gpio_get(struct gpio_chip *chip, unsigned offset) | ||||
| +{ | ||||
| +	struct mtk_gc *rg = to_mediatek_gpio(chip); | ||||
| + | ||||
| +	return !!(mtk_gpio_r32(rg, GPIO_REG_DATA) & BIT(offset)); | ||||
| +} | ||||
| + | ||||
| +static int | ||||
| +mediatek_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | ||||
| +{ | ||||
| +	struct mtk_gc *rg = to_mediatek_gpio(chip); | ||||
| +	unsigned long flags; | ||||
| +	u32 t; | ||||
| + | ||||
| +	spin_lock_irqsave(&rg->lock, flags); | ||||
| +	t = mtk_gpio_r32(rg, GPIO_REG_CTRL); | ||||
| +	t &= ~BIT(offset); | ||||
| +	mtk_gpio_w32(rg, GPIO_REG_CTRL, t); | ||||
| +	spin_unlock_irqrestore(&rg->lock, flags); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static int | ||||
| +mediatek_gpio_direction_output(struct gpio_chip *chip, | ||||
| +					unsigned offset, int value) | ||||
| +{ | ||||
| +	struct mtk_gc *rg = to_mediatek_gpio(chip); | ||||
| +	unsigned long flags; | ||||
| +	u32 t; | ||||
| + | ||||
| +	spin_lock_irqsave(&rg->lock, flags); | ||||
| +	t = mtk_gpio_r32(rg, GPIO_REG_CTRL); | ||||
| +	t |= BIT(offset); | ||||
| +	mtk_gpio_w32(rg, GPIO_REG_CTRL, t); | ||||
| +	mediatek_gpio_set(chip, offset, value); | ||||
| +	spin_unlock_irqrestore(&rg->lock, flags); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static int | ||||
| +mediatek_gpio_get_direction(struct gpio_chip *chip, unsigned offset) | ||||
| +{ | ||||
| +	struct mtk_gc *rg = to_mediatek_gpio(chip); | ||||
| +	unsigned long flags; | ||||
| +	u32 t; | ||||
| + | ||||
| +	spin_lock_irqsave(&rg->lock, flags); | ||||
| +	t = mtk_gpio_r32(rg, GPIO_REG_CTRL); | ||||
| +	spin_unlock_irqrestore(&rg->lock, flags); | ||||
| + | ||||
| +	if (t & BIT(offset)) | ||||
| +		return 0; | ||||
| + | ||||
| +	return 1; | ||||
| +} | ||||
| + | ||||
| +static int | ||||
| +mediatek_gpio_to_irq(struct gpio_chip *chip, unsigned pin) | ||||
| +{ | ||||
| +	struct mtk_gc *rg = to_mediatek_gpio(chip); | ||||
| + | ||||
| +	return irq_create_mapping(mediatek_gpio_irq_domain, pin + (rg->bank * MTK_BANK_WIDTH)); | ||||
| +} | ||||
| + | ||||
| +static int | ||||
| +mediatek_gpio_bank_probe(struct platform_device *pdev, struct device_node *bank) | ||||
| +{ | ||||
| +	const __be32 *id = of_get_property(bank, "reg", NULL); | ||||
| +	struct mtk_gc *rg = devm_kzalloc(&pdev->dev, | ||||
| +				sizeof(struct mtk_gc), GFP_KERNEL); | ||||
| + | ||||
| +	if (!rg || !id || be32_to_cpu(*id) > MTK_MAX_BANK) | ||||
| +		return -ENOMEM; | ||||
| + | ||||
| +	gc_map[be32_to_cpu(*id)] = rg; | ||||
| + | ||||
| +	memset(rg, 0, sizeof(struct mtk_gc)); | ||||
| + | ||||
| +	spin_lock_init(&rg->lock); | ||||
| + | ||||
| +	rg->chip.parent = &pdev->dev; | ||||
| +	rg->chip.label = dev_name(&pdev->dev); | ||||
| +	rg->chip.of_node = bank; | ||||
| +	rg->chip.base = MTK_BANK_WIDTH * be32_to_cpu(*id); | ||||
| +	rg->chip.ngpio = MTK_BANK_WIDTH; | ||||
| +	rg->chip.direction_input = mediatek_gpio_direction_input; | ||||
| +	rg->chip.direction_output = mediatek_gpio_direction_output; | ||||
| +	rg->chip.get_direction = mediatek_gpio_get_direction; | ||||
| +	rg->chip.get = mediatek_gpio_get; | ||||
| +	rg->chip.set = mediatek_gpio_set; | ||||
| +	if (mediatek_gpio_irq_domain) | ||||
| +		rg->chip.to_irq = mediatek_gpio_to_irq; | ||||
| +	rg->bank = be32_to_cpu(*id); | ||||
| + | ||||
| +	/* set polarity to low for all gpios */ | ||||
| +	mtk_gpio_w32(rg, GPIO_REG_POL, 0); | ||||
| + | ||||
| +	dev_info(&pdev->dev, "registering %d gpios\n", rg->chip.ngpio); | ||||
| + | ||||
| +	return gpiochip_add(&rg->chip); | ||||
| +} | ||||
| + | ||||
| +static void | ||||
| +mediatek_gpio_irq_handler(struct irq_desc *desc) | ||||
| +{ | ||||
| +	int i; | ||||
| + | ||||
| +	for (i = 0; i < MTK_MAX_BANK; i++) { | ||||
| +		struct mtk_gc *rg = gc_map[i]; | ||||
| +		unsigned long pending; | ||||
| +		int bit; | ||||
| + | ||||
| +		if (!rg) | ||||
| +			continue; | ||||
| + | ||||
| +		pending = mtk_gpio_r32(rg, GPIO_REG_STAT); | ||||
| + | ||||
| +		for_each_set_bit(bit, &pending, MTK_BANK_WIDTH) { | ||||
| +			u32 map = irq_find_mapping(mediatek_gpio_irq_domain, (MTK_BANK_WIDTH * i) + bit); | ||||
| + | ||||
| +			generic_handle_irq(map); | ||||
| +			mtk_gpio_w32(rg, GPIO_REG_STAT, BIT(bit)); | ||||
| +		} | ||||
| +	} | ||||
| +} | ||||
| + | ||||
| +static void | ||||
| +mediatek_gpio_irq_unmask(struct irq_data *d) | ||||
| +{ | ||||
| +	int pin = d->hwirq; | ||||
| +	int bank = pin / 32; | ||||
| +	struct mtk_gc *rg = gc_map[bank]; | ||||
| +	unsigned long flags; | ||||
| +	u32 rise, fall; | ||||
| + | ||||
| +	if (!rg) | ||||
| +		return; | ||||
| + | ||||
| +	rise = mtk_gpio_r32(rg, GPIO_REG_REDGE); | ||||
| +	fall = mtk_gpio_r32(rg, GPIO_REG_FEDGE); | ||||
| + | ||||
| +	spin_lock_irqsave(&rg->lock, flags); | ||||
| +	mtk_gpio_w32(rg, GPIO_REG_REDGE, rise | (BIT(d->hwirq) & rg->rising)); | ||||
| +	mtk_gpio_w32(rg, GPIO_REG_FEDGE, fall | (BIT(d->hwirq) & rg->falling)); | ||||
| +	spin_unlock_irqrestore(&rg->lock, flags); | ||||
| +} | ||||
| + | ||||
| +static void | ||||
| +mediatek_gpio_irq_mask(struct irq_data *d) | ||||
| +{ | ||||
| +	int pin = d->hwirq; | ||||
| +	int bank = pin / 32; | ||||
| +	struct mtk_gc *rg = gc_map[bank]; | ||||
| +	unsigned long flags; | ||||
| +	u32 rise, fall; | ||||
| + | ||||
| +	if (!rg) | ||||
| +		return; | ||||
| + | ||||
| +	rise = mtk_gpio_r32(rg, GPIO_REG_REDGE); | ||||
| +	fall = mtk_gpio_r32(rg, GPIO_REG_FEDGE); | ||||
| + | ||||
| +	spin_lock_irqsave(&rg->lock, flags); | ||||
| +	mtk_gpio_w32(rg, GPIO_REG_FEDGE, fall & ~BIT(d->hwirq)); | ||||
| +	mtk_gpio_w32(rg, GPIO_REG_REDGE, rise & ~BIT(d->hwirq)); | ||||
| +	spin_unlock_irqrestore(&rg->lock, flags); | ||||
| +} | ||||
| + | ||||
| +static int | ||||
| +mediatek_gpio_irq_type(struct irq_data *d, unsigned int type) | ||||
| +{ | ||||
| +	int pin = d->hwirq; | ||||
| +	int bank = pin / 32; | ||||
| +	struct mtk_gc *rg = gc_map[bank]; | ||||
| +	u32 mask = BIT(d->hwirq); | ||||
| + | ||||
| +	if (!rg) | ||||
| +		return -1; | ||||
| + | ||||
| +	if (type == IRQ_TYPE_PROBE) { | ||||
| +		if ((rg->rising | rg->falling) & mask) | ||||
| +			return 0; | ||||
| + | ||||
| +		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING; | ||||
| +	} | ||||
| + | ||||
| +	if (type & IRQ_TYPE_EDGE_RISING) | ||||
| +		rg->rising |= mask; | ||||
| +	else | ||||
| +		rg->rising &= ~mask; | ||||
| + | ||||
| +	if (type & IRQ_TYPE_EDGE_FALLING) | ||||
| +		rg->falling |= mask; | ||||
| +	else | ||||
| +		rg->falling &= ~mask; | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static struct irq_chip mediatek_gpio_irq_chip = { | ||||
| +	.name		= "GPIO", | ||||
| +	.irq_unmask	= mediatek_gpio_irq_unmask, | ||||
| +	.irq_mask	= mediatek_gpio_irq_mask, | ||||
| +	.irq_mask_ack	= mediatek_gpio_irq_mask, | ||||
| +	.irq_set_type	= mediatek_gpio_irq_type, | ||||
| +}; | ||||
| + | ||||
| +static int | ||||
| +mediatek_gpio_gpio_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) | ||||
| +{ | ||||
| +	irq_set_chip_and_handler(irq, &mediatek_gpio_irq_chip, handle_level_irq); | ||||
| +	irq_set_handler_data(irq, d); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static const struct irq_domain_ops irq_domain_ops = { | ||||
| +	.xlate = irq_domain_xlate_onecell, | ||||
| +	.map = mediatek_gpio_gpio_map, | ||||
| +}; | ||||
| + | ||||
| +static int | ||||
| +mediatek_gpio_probe(struct platform_device *pdev) | ||||
| +{ | ||||
| +	struct device_node *bank, *np = pdev->dev.of_node; | ||||
| +	struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||||
| + | ||||
| +	mediatek_gpio_membase = devm_ioremap_resource(&pdev->dev, res); | ||||
| +	if (IS_ERR(mediatek_gpio_membase)) | ||||
| +		return PTR_ERR(mediatek_gpio_membase); | ||||
| + | ||||
| +	mediatek_gpio_irq = irq_of_parse_and_map(np, 0); | ||||
| +	if (mediatek_gpio_irq) { | ||||
| +		mediatek_gpio_irq_domain = irq_domain_add_linear(np, | ||||
| +			MTK_MAX_BANK * MTK_BANK_WIDTH, | ||||
| +			&irq_domain_ops, NULL); | ||||
| +		if (!mediatek_gpio_irq_domain) | ||||
| +			dev_err(&pdev->dev, "irq_domain_add_linear failed\n"); | ||||
| +	} | ||||
| + | ||||
| +	for_each_child_of_node(np, bank) | ||||
| +		if (of_device_is_compatible(bank, "mtk,mt7621-gpio-bank")) | ||||
| +			mediatek_gpio_bank_probe(pdev, bank); | ||||
| + | ||||
| +	if (mediatek_gpio_irq_domain) | ||||
| +		irq_set_chained_handler(mediatek_gpio_irq, mediatek_gpio_irq_handler); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static const struct of_device_id mediatek_gpio_match[] = { | ||||
| +	{ .compatible = "mtk,mt7621-gpio" }, | ||||
| +	{}, | ||||
| +}; | ||||
| +MODULE_DEVICE_TABLE(of, mediatek_gpio_match); | ||||
| + | ||||
| +static struct platform_driver mediatek_gpio_driver = { | ||||
| +	.probe = mediatek_gpio_probe, | ||||
| +	.driver = { | ||||
| +		.name = "mt7621_gpio", | ||||
| +		.owner = THIS_MODULE, | ||||
| +		.of_match_table = mediatek_gpio_match, | ||||
| +	}, | ||||
| +}; | ||||
| + | ||||
| +static int __init | ||||
| +mediatek_gpio_init(void) | ||||
| +{ | ||||
| +	return platform_driver_register(&mediatek_gpio_driver); | ||||
| +} | ||||
| + | ||||
| +subsys_initcall(mediatek_gpio_init); | ||||
| @@ -0,0 +1,293 @@ | ||||
| From b00b5eafa7e8d059bd0ce844e66f648916953270 Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <blogic@openwrt.org> | ||||
| Date: Sun, 3 Jan 2016 19:11:22 +0100 | ||||
| Subject: [PATCH 2/3] phy: ralink-usb: add driver for Mediatek/Ralink | ||||
|  | ||||
| Add a driver to setup the USB phy on Mediatek/Ralink SoCs. | ||||
| The driver is trivial and only sets up power and host mode. | ||||
|  | ||||
| Signed-off-by: John Crispin <blogic@openwrt.org> | ||||
| --- | ||||
|  .../devicetree/bindings/phy/ralink-usb-phy.txt     |   17 ++ | ||||
|  drivers/phy/Kconfig                                |    8 + | ||||
|  drivers/phy/Makefile                               |    1 + | ||||
|  drivers/phy/phy-ralink-usb.c                       |  171 ++++++++++++++++++++ | ||||
|  4 files changed, 197 insertions(+) | ||||
|  create mode 100644 Documentation/devicetree/bindings/phy/ralink-usb-phy.txt | ||||
|  create mode 100644 drivers/phy/phy-ralink-usb.c | ||||
|  | ||||
| --- /dev/null | ||||
| +++ b/Documentation/devicetree/bindings/phy/ralink-usb-phy.txt | ||||
| @@ -0,0 +1,17 @@ | ||||
| +Mediatek/Ralink USB PHY | ||||
| + | ||||
| +Required properties: | ||||
| + - compatible: ralink,rt3352-usbphy or mediatek,mt7620-usbphy | ||||
| + - #phy-cells: should be 0 | ||||
| + - resets: the two reset controllers for host and device | ||||
| + - reset-names: the names of the 2 reset controllers | ||||
| + | ||||
| +Example: | ||||
| + | ||||
| +usbphy: phy { | ||||
| +	compatible = "mediatek,mt7620-usbphy"; | ||||
| +	#phy-cells = <0>; | ||||
| + | ||||
| +	resets = <&rstctrl 22 &rstctrl 25>; | ||||
| +	reset-names = "host", "device"; | ||||
| +}; | ||||
| --- a/drivers/phy/Kconfig | ||||
| +++ b/drivers/phy/Kconfig | ||||
| @@ -429,6 +429,14 @@ config PHY_XGENE | ||||
|  	help | ||||
|  	  This option enables support for APM X-Gene SoC multi-purpose PHY. | ||||
|   | ||||
| +config PHY_RALINK_USB | ||||
| +	tristate "Ralink USB PHY driver" | ||||
| +	select GENERIC_PHY | ||||
| +	depends on RALINK | ||||
| +	help | ||||
| +	  This option enables support for the Ralink USB PHY found inside | ||||
| +	  RT3352 and MT7620. | ||||
| + | ||||
|  config PHY_STIH407_USB | ||||
|  	tristate "STMicroelectronics USB2 picoPHY driver for STiH407 family" | ||||
|  	depends on RESET_CONTROLLER | ||||
| --- a/drivers/phy/Makefile | ||||
| +++ b/drivers/phy/Makefile | ||||
| @@ -60,3 +60,4 @@ obj-$(CONFIG_PHY_PISTACHIO_USB)		+= phy- | ||||
|  obj-$(CONFIG_PHY_CYGNUS_PCIE)		+= phy-bcm-cygnus-pcie.o | ||||
|  obj-$(CONFIG_ARCH_TEGRA) += tegra/ | ||||
|  obj-$(CONFIG_PHY_NS2_PCIE)		+= phy-bcm-ns2-pcie.o | ||||
| +obj-$(CONFIG_PHY_RALINK_USB)		+= phy-ralink-usb.o | ||||
| --- /dev/null | ||||
| +++ b/drivers/phy/phy-ralink-usb.c | ||||
| @@ -0,0 +1,228 @@ | ||||
| +/* | ||||
| + * Allwinner ralink USB phy driver | ||||
| + * | ||||
| + * Copyright (C) 2016 John Crispin <blogic@openwrt.org> | ||||
| + * | ||||
| + * Based on code from | ||||
| + * Allwinner Technology Co., Ltd. <www.allwinnertech.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 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 <linux/delay.h> | ||||
| +#include <linux/err.h> | ||||
| +#include <linux/io.h> | ||||
| +#include <linux/kernel.h> | ||||
| +#include <linux/module.h> | ||||
| +#include <linux/mutex.h> | ||||
| +#include <linux/phy/phy.h> | ||||
| +#include <linux/platform_device.h> | ||||
| +#include <linux/reset.h> | ||||
| +#include <linux/of_platform.h> | ||||
| + | ||||
| +#include <asm/mach-ralink/ralink_regs.h> | ||||
| + | ||||
| +#define RT_SYSC_REG_SYSCFG1		0x014 | ||||
| +#define RT_SYSC_REG_CLKCFG1		0x030 | ||||
| +#define RT_SYSC_REG_USB_PHY_CFG		0x05c | ||||
| + | ||||
| +#define OFS_U2_PHY_AC0                  0x800 | ||||
| +#define OFS_U2_PHY_AC1                  0x804 | ||||
| +#define OFS_U2_PHY_AC2                  0x808 | ||||
| +#define OFS_U2_PHY_ACR0                 0x810 | ||||
| +#define OFS_U2_PHY_ACR1                 0x814 | ||||
| +#define OFS_U2_PHY_ACR2                 0x818 | ||||
| +#define OFS_U2_PHY_ACR3                 0x81C | ||||
| +#define OFS_U2_PHY_ACR4                 0x820 | ||||
| +#define OFS_U2_PHY_AMON0                0x824 | ||||
| +#define OFS_U2_PHY_DCR0                 0x860 | ||||
| +#define OFS_U2_PHY_DCR1                 0x864 | ||||
| +#define OFS_U2_PHY_DTM0                 0x868 | ||||
| +#define OFS_U2_PHY_DTM1                 0x86C | ||||
| + | ||||
| +#define RT_RSTCTRL_UDEV			BIT(25) | ||||
| +#define RT_RSTCTRL_UHST			BIT(22) | ||||
| +#define RT_SYSCFG1_USB0_HOST_MODE	BIT(10) | ||||
| + | ||||
| +#define MT7620_CLKCFG1_UPHY0_CLK_EN	BIT(25) | ||||
| +#define MT7620_CLKCFG1_UPHY1_CLK_EN	BIT(22) | ||||
| +#define RT_CLKCFG1_UPHY1_CLK_EN		BIT(20) | ||||
| +#define RT_CLKCFG1_UPHY0_CLK_EN		BIT(18) | ||||
| + | ||||
| +#define USB_PHY_UTMI_8B60M		BIT(1) | ||||
| +#define UDEV_WAKEUP			BIT(0) | ||||
| + | ||||
| +struct ralink_usb_phy { | ||||
| +	struct reset_control	*rstdev; | ||||
| +	struct reset_control	*rsthost; | ||||
| +	u32			clk; | ||||
| +	struct phy		*phy; | ||||
| +	void __iomem		*base; | ||||
| +}; | ||||
| + | ||||
| +static void u2_phy_w32(struct ralink_usb_phy *phy, u32 val, u32 reg) | ||||
| +{ | ||||
| +	iowrite32(val, phy->base + reg); | ||||
| +} | ||||
| + | ||||
| +static u32 u2_phy_r32(struct ralink_usb_phy *phy, u32 reg) | ||||
| +{ | ||||
| +	return ioread32(phy->base + reg); | ||||
| +} | ||||
| + | ||||
| +static void | ||||
| +u2_phy_init(struct ralink_usb_phy *phy) | ||||
| +{ | ||||
| +	u2_phy_r32(phy, OFS_U2_PHY_AC2); | ||||
| +	u2_phy_r32(phy, OFS_U2_PHY_ACR0); | ||||
| +	u2_phy_r32(phy, OFS_U2_PHY_DCR0); | ||||
| + | ||||
| +	u2_phy_w32(phy, 0x00ffff02, OFS_U2_PHY_DCR0); | ||||
| +	u2_phy_r32(phy, OFS_U2_PHY_DCR0); | ||||
| +	u2_phy_w32(phy, 0x00555502, OFS_U2_PHY_DCR0); | ||||
| +	u2_phy_r32(phy, OFS_U2_PHY_DCR0); | ||||
| +	u2_phy_w32(phy, 0x00aaaa02, OFS_U2_PHY_DCR0); | ||||
| +	u2_phy_r32(phy, OFS_U2_PHY_DCR0); | ||||
| +	u2_phy_w32(phy, 0x00000402, OFS_U2_PHY_DCR0); | ||||
| +	u2_phy_r32(phy, OFS_U2_PHY_DCR0); | ||||
| +	u2_phy_w32(phy, 0x0048086a, OFS_U2_PHY_AC0); | ||||
| +	u2_phy_w32(phy, 0x4400001c, OFS_U2_PHY_AC1); | ||||
| +	u2_phy_w32(phy, 0xc0200000, OFS_U2_PHY_ACR3); | ||||
| +	u2_phy_w32(phy, 0x02000000, OFS_U2_PHY_DTM0); | ||||
| +} | ||||
| + | ||||
| +static int ralink_usb_phy_power_on(struct phy *_phy) | ||||
| +{ | ||||
| +	struct ralink_usb_phy *phy = phy_get_drvdata(_phy); | ||||
| +	u32 t; | ||||
| + | ||||
| +	/* enable the phy */ | ||||
| +	rt_sysc_m32(0, phy->clk, RT_SYSC_REG_CLKCFG1); | ||||
| + | ||||
| +	/* setup host mode */ | ||||
| +	rt_sysc_m32(0, RT_SYSCFG1_USB0_HOST_MODE, RT_SYSC_REG_SYSCFG1); | ||||
| + | ||||
| +	/* deassert the reset lines */ | ||||
| +	reset_control_deassert(phy->rsthost); | ||||
| +	reset_control_deassert(phy->rstdev); | ||||
| + | ||||
| +	/* | ||||
| +	 * The SDK kernel had a delay of 100ms. however on device | ||||
| +	 * testing showed that 10ms is enough | ||||
| +	 */ | ||||
| +	mdelay(10); | ||||
| + | ||||
| +	if (!IS_ERR(phy->base)) | ||||
| +		u2_phy_init(phy); | ||||
| + | ||||
| +	/* print some status info */ | ||||
| +	t = rt_sysc_r32(RT_SYSC_REG_USB_PHY_CFG); | ||||
| +	dev_info(&phy->phy->dev, "remote usb device wakeup %s\n", | ||||
| +		(t & UDEV_WAKEUP) ? ("enabled") : ("disabled")); | ||||
| +	if (t & USB_PHY_UTMI_8B60M) | ||||
| +		dev_info(&phy->phy->dev, "UTMI 8bit 60MHz\n"); | ||||
| +	else | ||||
| +		dev_info(&phy->phy->dev, "UTMI 16bit 30MHz\n"); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static int ralink_usb_phy_power_off(struct phy *_phy) | ||||
| +{ | ||||
| +	struct ralink_usb_phy *phy = phy_get_drvdata(_phy); | ||||
| + | ||||
| +	/* assert the reset lines */ | ||||
| +	reset_control_assert(phy->rstdev); | ||||
| +	reset_control_assert(phy->rsthost); | ||||
| + | ||||
| +	/* disable the phy */ | ||||
| +	rt_sysc_m32(phy->clk, 0, RT_SYSC_REG_CLKCFG1); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static struct phy_ops ralink_usb_phy_ops = { | ||||
| +	.power_on	= ralink_usb_phy_power_on, | ||||
| +	.power_off	= ralink_usb_phy_power_off, | ||||
| +	.owner		= THIS_MODULE, | ||||
| +}; | ||||
| + | ||||
| +static const struct of_device_id ralink_usb_phy_of_match[] = { | ||||
| +	{ | ||||
| +		.compatible = "ralink,rt3352-usbphy", | ||||
| +		.data = (void *) (RT_CLKCFG1_UPHY1_CLK_EN | | ||||
| +				  RT_CLKCFG1_UPHY0_CLK_EN) | ||||
| +	}, | ||||
| +	{ | ||||
| +		.compatible = "mediatek,mt7620-usbphy", | ||||
| +		.data = (void *) (MT7620_CLKCFG1_UPHY1_CLK_EN | | ||||
| +				  MT7620_CLKCFG1_UPHY0_CLK_EN) }, | ||||
| +	{ }, | ||||
| +}; | ||||
| +MODULE_DEVICE_TABLE(of, ralink_usb_phy_of_match); | ||||
| + | ||||
| +static int ralink_usb_phy_probe(struct platform_device *pdev) | ||||
| +{ | ||||
| +	struct resource *res; | ||||
| +	struct device *dev = &pdev->dev; | ||||
| +	struct phy_provider *phy_provider; | ||||
| +	const struct of_device_id *match; | ||||
| +	struct ralink_usb_phy *phy; | ||||
| + | ||||
| +	phy = devm_kzalloc(dev, sizeof(*phy), GFP_KERNEL); | ||||
| +	if (!phy) | ||||
| +		return -ENOMEM; | ||||
| + | ||||
| +	match = of_match_device(ralink_usb_phy_of_match, &pdev->dev); | ||||
| +	if (!match) | ||||
| +		return -ENODEV; | ||||
| + | ||||
| +	phy->clk = (int) match->data; | ||||
| + | ||||
| +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||||
| +	phy->base = devm_ioremap_resource(&pdev->dev, res); | ||||
| + | ||||
| +	phy->rsthost = devm_reset_control_get(&pdev->dev, "host"); | ||||
| +	if (IS_ERR(phy->rsthost)) { | ||||
| +		dev_err(dev, "host reset is missing\n"); | ||||
| +		return PTR_ERR(phy->rsthost); | ||||
| +	} | ||||
| + | ||||
| +	phy->rstdev = devm_reset_control_get(&pdev->dev, "device"); | ||||
| +	if (IS_ERR(phy->rstdev)) { | ||||
| +		dev_err(dev, "device reset is missing\n"); | ||||
| +		return PTR_ERR(phy->rstdev); | ||||
| +	} | ||||
| + | ||||
| +	phy->phy = devm_phy_create(dev, NULL, &ralink_usb_phy_ops); | ||||
| +	if (IS_ERR(phy->phy)) { | ||||
| +		dev_err(dev, "failed to create PHY\n"); | ||||
| +		return PTR_ERR(phy->phy); | ||||
| +	} | ||||
| +	phy_set_drvdata(phy->phy, phy); | ||||
| + | ||||
| +	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); | ||||
| + | ||||
| +	return PTR_ERR_OR_ZERO(phy_provider); | ||||
| +} | ||||
| + | ||||
| +static struct platform_driver ralink_usb_phy_driver = { | ||||
| +	.probe	= ralink_usb_phy_probe, | ||||
| +	.driver = { | ||||
| +		.of_match_table	= ralink_usb_phy_of_match, | ||||
| +		.name  = "ralink-usb-phy", | ||||
| +	} | ||||
| +}; | ||||
| +module_platform_driver(ralink_usb_phy_driver); | ||||
| + | ||||
| +MODULE_DESCRIPTION("Ralink USB phy driver"); | ||||
| +MODULE_AUTHOR("John Crispin <blogic@openwrt.org>"); | ||||
| +MODULE_LICENSE("GPL v2"); | ||||
| @@ -0,0 +1,246 @@ | ||||
| From 975e76214cd2516eb6cfff4c3eec581872645e88 Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <blogic@openwrt.org> | ||||
| Date: Thu, 19 Sep 2013 01:50:59 +0200 | ||||
| Subject: [PATCH 31/53] uvc: add iPassion iP2970 support | ||||
|  | ||||
| Signed-off-by: John Crispin <blogic@openwrt.org> | ||||
| --- | ||||
|  drivers/media/usb/uvc/uvc_driver.c |   12 +++ | ||||
|  drivers/media/usb/uvc/uvc_status.c |    2 + | ||||
|  drivers/media/usb/uvc/uvc_video.c  |  147 ++++++++++++++++++++++++++++++++++++ | ||||
|  drivers/media/usb/uvc/uvcvideo.h   |    5 +- | ||||
|  4 files changed, 165 insertions(+), 1 deletion(-) | ||||
|  | ||||
| --- a/drivers/media/usb/uvc/uvc_driver.c | ||||
| +++ b/drivers/media/usb/uvc/uvc_driver.c | ||||
| @@ -2564,6 +2564,18 @@ static struct usb_device_id uvc_ids[] = | ||||
|  	  .bInterfaceSubClass	= 1, | ||||
|  	  .bInterfaceProtocol	= 0, | ||||
|  	  .driver_info		= UVC_QUIRK_FORCE_Y8 }, | ||||
| +	/* iPassion iP2970 */ | ||||
| +	{ .match_flags          = USB_DEVICE_ID_MATCH_DEVICE | ||||
| +				| USB_DEVICE_ID_MATCH_INT_INFO, | ||||
| +	 .idVendor		= 0x1B3B, | ||||
| +	 .idProduct		= 0x2970, | ||||
| +	 .bInterfaceClass	= USB_CLASS_VIDEO, | ||||
| +	 .bInterfaceSubClass	= 1, | ||||
| +	 .bInterfaceProtocol	= 0, | ||||
| +	 .driver_info		= UVC_QUIRK_PROBE_MINMAX | ||||
| +				| UVC_QUIRK_STREAM_NO_FID | ||||
| +				| UVC_QUIRK_MOTION | ||||
| +				| UVC_QUIRK_SINGLE_ISO }, | ||||
|  	/* Generic USB Video Class */ | ||||
|  	{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_UNDEFINED) }, | ||||
|  	{ USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, UVC_PC_PROTOCOL_15) }, | ||||
| --- a/drivers/media/usb/uvc/uvc_status.c | ||||
| +++ b/drivers/media/usb/uvc/uvc_status.c | ||||
| @@ -139,6 +139,7 @@ static void uvc_status_complete(struct u | ||||
|  		switch (dev->status[0] & 0x0f) { | ||||
|  		case UVC_STATUS_TYPE_CONTROL: | ||||
|  			uvc_event_control(dev, dev->status, len); | ||||
| +			dev->motion = 1; | ||||
|  			break; | ||||
|   | ||||
|  		case UVC_STATUS_TYPE_STREAMING: | ||||
| @@ -182,6 +183,7 @@ int uvc_status_init(struct uvc_device *d | ||||
|  	} | ||||
|   | ||||
|  	pipe = usb_rcvintpipe(dev->udev, ep->desc.bEndpointAddress); | ||||
| +	dev->motion = 0; | ||||
|   | ||||
|  	/* For high-speed interrupt endpoints, the bInterval value is used as | ||||
|  	 * an exponent of two. Some developers forgot about it. | ||||
| --- a/drivers/media/usb/uvc/uvc_video.c | ||||
| +++ b/drivers/media/usb/uvc/uvc_video.c | ||||
| @@ -21,6 +21,11 @@ | ||||
|  #include <linux/wait.h> | ||||
|  #include <linux/atomic.h> | ||||
|  #include <asm/unaligned.h> | ||||
| +#include <linux/skbuff.h> | ||||
| +#include <linux/kobject.h> | ||||
| +#include <linux/netlink.h> | ||||
| +#include <linux/kobject.h> | ||||
| +#include <linux/workqueue.h> | ||||
|   | ||||
|  #include <media/v4l2-common.h> | ||||
|   | ||||
| @@ -1087,9 +1092,149 @@ static void uvc_video_decode_data(struct | ||||
|  	} | ||||
|  } | ||||
|   | ||||
| +struct bh_priv { | ||||
| +	unsigned long	seen; | ||||
| +}; | ||||
| + | ||||
| +struct bh_event { | ||||
| +	const char		*name; | ||||
| +	struct sk_buff		*skb; | ||||
| +	struct work_struct	work; | ||||
| +}; | ||||
| + | ||||
| +#define BH_ERR(fmt, args...) printk(KERN_ERR "%s: " fmt, "webcam", ##args ) | ||||
| +#define BH_DBG(fmt, args...) do {} while (0) | ||||
| +#define BH_SKB_SIZE     2048 | ||||
| + | ||||
| +extern u64 uevent_next_seqnum(void); | ||||
| +static int seen = 0; | ||||
| + | ||||
| +static int bh_event_add_var(struct bh_event *event, int argv, | ||||
| +		const char *format, ...) | ||||
| +{ | ||||
| +	static char buf[128]; | ||||
| +	char *s; | ||||
| +	va_list args; | ||||
| +	int len; | ||||
| + | ||||
| +	if (argv) | ||||
| +		return 0; | ||||
| + | ||||
| +	va_start(args, format); | ||||
| +	len = vsnprintf(buf, sizeof(buf), format, args); | ||||
| +	va_end(args); | ||||
| + | ||||
| +	if (len >= sizeof(buf)) { | ||||
| +		BH_ERR("buffer size too small\n"); | ||||
| +		WARN_ON(1); | ||||
| +		return -ENOMEM; | ||||
| +	} | ||||
| + | ||||
| +	s = skb_put(event->skb, len + 1); | ||||
| +	strcpy(s, buf); | ||||
| + | ||||
| +	BH_DBG("added variable '%s'\n", s); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static int motion_hotplug_fill_event(struct bh_event *event) | ||||
| +{ | ||||
| +	int s = jiffies; | ||||
| +	int ret; | ||||
| + | ||||
| +	if (!seen) | ||||
| +		seen = jiffies; | ||||
| + | ||||
| +	ret = bh_event_add_var(event, 0, "HOME=%s", "/"); | ||||
| +	if (ret) | ||||
| +		return ret; | ||||
| + | ||||
| +	ret = bh_event_add_var(event, 0, "PATH=%s", | ||||
| +		"/sbin:/bin:/usr/sbin:/usr/bin"); | ||||
| +	if (ret) | ||||
| +		return ret; | ||||
| + | ||||
| +	ret = bh_event_add_var(event, 0, "SUBSYSTEM=usb"); | ||||
| +	if (ret) | ||||
| +		return ret; | ||||
| + | ||||
| +	ret = bh_event_add_var(event, 0, "ACTION=motion"); | ||||
| +	if (ret) | ||||
| +		return ret; | ||||
| + | ||||
| +	ret = bh_event_add_var(event, 0, "SEEN=%d", s - seen); | ||||
| +	if (ret) | ||||
| +		return ret; | ||||
| +	seen = s; | ||||
| + | ||||
| +	ret = bh_event_add_var(event, 0, "SEQNUM=%llu", uevent_next_seqnum()); | ||||
| + | ||||
| +	return ret; | ||||
| +} | ||||
| + | ||||
| +static void motion_hotplug_work(struct work_struct *work) | ||||
| +{ | ||||
| +	struct bh_event *event = container_of(work, struct bh_event, work); | ||||
| +	int ret = 0; | ||||
| + | ||||
| +	event->skb = alloc_skb(BH_SKB_SIZE, GFP_KERNEL); | ||||
| +	if (!event->skb) | ||||
| +		goto out_free_event; | ||||
| + | ||||
| +	ret = bh_event_add_var(event, 0, "%s@", "add"); | ||||
| +	if (ret) | ||||
| +		goto out_free_skb; | ||||
| + | ||||
| +	ret = motion_hotplug_fill_event(event); | ||||
| +	if (ret) | ||||
| +		goto out_free_skb; | ||||
| + | ||||
| +	NETLINK_CB(event->skb).dst_group = 1; | ||||
| +	broadcast_uevent(event->skb, 0, 1, GFP_KERNEL); | ||||
| + | ||||
| +out_free_skb: | ||||
| +	if (ret) { | ||||
| +		BH_ERR("work error %d\n", ret); | ||||
| +		kfree_skb(event->skb); | ||||
| +	} | ||||
| +out_free_event: | ||||
| +	kfree(event); | ||||
| +} | ||||
| + | ||||
| +static int motion_hotplug_create_event(void) | ||||
| +{ | ||||
| +	struct bh_event *event; | ||||
| + | ||||
| +	event = kzalloc(sizeof(*event), GFP_KERNEL); | ||||
| +	if (!event) | ||||
| +		return -ENOMEM; | ||||
| + | ||||
| +	event->name = "motion"; | ||||
| + | ||||
| +	INIT_WORK(&event->work, (void *)(void *)motion_hotplug_work); | ||||
| +	schedule_work(&event->work); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +#define MOTION_FLAG_OFFSET	4 | ||||
|  static void uvc_video_decode_end(struct uvc_streaming *stream, | ||||
|  		struct uvc_buffer *buf, const __u8 *data, int len) | ||||
|  { | ||||
| +	if ((stream->dev->quirks & UVC_QUIRK_MOTION) && | ||||
| +			(data[len - 2] == 0xff) && (data[len - 1] == 0xd9)) { | ||||
| +		u8 *mem; | ||||
| +		buf->state = UVC_BUF_STATE_READY; | ||||
| +		mem = (u8 *) (buf->mem + MOTION_FLAG_OFFSET); | ||||
| +		if ( stream->dev->motion ) { | ||||
| +			stream->dev->motion = 0; | ||||
| +			motion_hotplug_create_event(); | ||||
| +		} else { | ||||
| +			*mem &= 0x7f; | ||||
| +		} | ||||
| +	} | ||||
| + | ||||
|  	/* Mark the buffer as done if the EOF marker is set. */ | ||||
|  	if (data[1] & UVC_STREAM_EOF && buf->bytesused != 0) { | ||||
|  		uvc_trace(UVC_TRACE_FRAME, "Frame complete (EOF found).\n"); | ||||
| @@ -1503,6 +1648,8 @@ static int uvc_init_video_isoc(struct uv | ||||
|  	if (npackets == 0) | ||||
|  		return -ENOMEM; | ||||
|   | ||||
| +	if (stream->dev->quirks & UVC_QUIRK_SINGLE_ISO) | ||||
| +		npackets = 1; | ||||
|  	size = npackets * psize; | ||||
|   | ||||
|  	for (i = 0; i < UVC_URBS; ++i) { | ||||
| --- a/drivers/media/usb/uvc/uvcvideo.h | ||||
| +++ b/drivers/media/usb/uvc/uvcvideo.h | ||||
| @@ -164,7 +164,9 @@ | ||||
|  #define UVC_QUIRK_RESTRICT_FRAME_RATE	0x00000200 | ||||
|  #define UVC_QUIRK_RESTORE_CTRLS_ON_INIT	0x00000400 | ||||
|  #define UVC_QUIRK_FORCE_Y8		0x00000800 | ||||
| - | ||||
| +#define UVC_QUIRK_MOTION		0x00001000 | ||||
| +#define UVC_QUIRK_SINGLE_ISO		0x00002000 | ||||
| +  | ||||
|  /* Format flags */ | ||||
|  #define UVC_FMT_FLAG_COMPRESSED		0x00000001 | ||||
|  #define UVC_FMT_FLAG_STREAM		0x00000002 | ||||
| @@ -562,6 +564,7 @@ struct uvc_device { | ||||
|  	__u8 *status; | ||||
|  	struct input_dev *input; | ||||
|  	char input_phys[64]; | ||||
| +	int motion; | ||||
|  }; | ||||
|   | ||||
|  enum uvc_handle_state { | ||||
| @@ -0,0 +1,29 @@ | ||||
| From a758e0870c6d1e4b0272f6e7f9efa9face5534bb Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <blogic@openwrt.org> | ||||
| Date: Sun, 27 Jul 2014 09:49:07 +0100 | ||||
| Subject: [PATCH 32/53] USB: dwc2: add device_reset() | ||||
|  | ||||
| Signed-off-by: John Crispin <blogic@openwrt.org> | ||||
| --- | ||||
|  drivers/usb/dwc2/hcd.c |    3 +++ | ||||
|  1 file changed, 3 insertions(+) | ||||
|  | ||||
| --- a/drivers/usb/dwc2/hcd.c | ||||
| +++ b/drivers/usb/dwc2/hcd.c | ||||
| @@ -47,6 +47,7 @@ | ||||
|  #include <linux/io.h> | ||||
|  #include <linux/slab.h> | ||||
|  #include <linux/usb.h> | ||||
| +#include <linux/reset.h> | ||||
|   | ||||
|  #include <linux/usb/hcd.h> | ||||
|  #include <linux/usb/ch11.h> | ||||
| @@ -4982,6 +4983,8 @@ int dwc2_hcd_init(struct dwc2_hsotg *hso | ||||
|   | ||||
|  	retval = -ENOMEM; | ||||
|   | ||||
| +	device_reset(hsotg->dev); | ||||
| + | ||||
|  	hcfg = dwc2_readl(hsotg->regs + HCFG); | ||||
|  	dev_dbg(hsotg->dev, "hcfg=%08x\n", hcfg); | ||||
|   | ||||
| @@ -0,0 +1,53 @@ | ||||
| From 0b6eb1e68290243d439ee330ea8d0b239a5aec69 Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <blogic@openwrt.org> | ||||
| Date: Sun, 27 Jul 2014 09:38:50 +0100 | ||||
| Subject: [PATCH 34/53] NET: multi phy support | ||||
|  | ||||
| Signed-off-by: John Crispin <blogic@openwrt.org> | ||||
| --- | ||||
|  drivers/net/phy/phy.c |    9 ++++++--- | ||||
|  include/linux/phy.h   |    1 + | ||||
|  2 files changed, 7 insertions(+), 3 deletions(-) | ||||
|  | ||||
| --- a/drivers/net/phy/phy.c | ||||
| +++ b/drivers/net/phy/phy.c | ||||
| @@ -996,7 +996,8 @@ void phy_state_machine(struct work_struc | ||||
|  		/* If the link is down, give up on negotiation for now */ | ||||
|  		if (!phydev->link) { | ||||
|  			phydev->state = PHY_NOLINK; | ||||
| -			netif_carrier_off(phydev->attached_dev); | ||||
| +			if (!phydev->no_auto_carrier_off) | ||||
| +				netif_carrier_off(phydev->attached_dev); | ||||
|  			phydev->adjust_link(phydev->attached_dev); | ||||
|  			break; | ||||
|  		} | ||||
| @@ -1079,7 +1080,8 @@ void phy_state_machine(struct work_struc | ||||
|  			netif_carrier_on(phydev->attached_dev); | ||||
|  		} else { | ||||
|  			phydev->state = PHY_NOLINK; | ||||
| -			netif_carrier_off(phydev->attached_dev); | ||||
| +			if (!phydev->no_auto_carrier_off) | ||||
| +				netif_carrier_off(phydev->attached_dev); | ||||
|  		} | ||||
|   | ||||
|  		phydev->adjust_link(phydev->attached_dev); | ||||
| @@ -1091,7 +1093,8 @@ void phy_state_machine(struct work_struc | ||||
|  	case PHY_HALTED: | ||||
|  		if (phydev->link) { | ||||
|  			phydev->link = 0; | ||||
| -			netif_carrier_off(phydev->attached_dev); | ||||
| +			if (!phydev->no_auto_carrier_off) | ||||
| +				netif_carrier_off(phydev->attached_dev); | ||||
|  			phydev->adjust_link(phydev->attached_dev); | ||||
|  			do_suspend = true; | ||||
|  		} | ||||
| --- a/include/linux/phy.h | ||||
| +++ b/include/linux/phy.h | ||||
| @@ -373,6 +373,7 @@ struct phy_device { | ||||
|  	bool is_pseudo_fixed_link; | ||||
|  	bool has_fixups; | ||||
|  	bool suspended; | ||||
| +	bool no_auto_carrier_off; | ||||
|   | ||||
|  	enum phy_state state; | ||||
|   | ||||
| @@ -0,0 +1,29 @@ | ||||
| From 8e72a3a1be8f6328bd7ef491332ba541547b6086 Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <blogic@openwrt.org> | ||||
| Date: Mon, 15 Jul 2013 00:38:51 +0200 | ||||
| Subject: [PATCH 36/53] mtd: fix cfi cmdset 0002 erase status check | ||||
|  | ||||
| --- | ||||
|  drivers/mtd/chips/cfi_cmdset_0002.c |    4 ++-- | ||||
|  1 file changed, 2 insertions(+), 2 deletions(-) | ||||
|  | ||||
| --- a/drivers/mtd/chips/cfi_cmdset_0002.c | ||||
| +++ b/drivers/mtd/chips/cfi_cmdset_0002.c | ||||
| @@ -2289,7 +2289,7 @@ static int __xipram do_erase_chip(struct | ||||
|  			chip->erase_suspended = 0; | ||||
|  		} | ||||
|   | ||||
| -		if (chip_ready(map, adr)) | ||||
| +		if (chip_good(map, adr, map_word_ff(map))) | ||||
|  			break; | ||||
|   | ||||
|  		if (time_after(jiffies, timeo)) { | ||||
| @@ -2378,7 +2378,7 @@ static int __xipram do_erase_oneblock(st | ||||
|  			chip->erase_suspended = 0; | ||||
|  		} | ||||
|   | ||||
| -		if (chip_ready(map, adr)) { | ||||
| +		if (chip_good(map, adr, map_word_ff(map))) { | ||||
|  			xip_enable(map, chip, adr); | ||||
|  			break; | ||||
|  		} | ||||
| @@ -0,0 +1,70 @@ | ||||
| From ee9081b2726a5ca8cde5497afdc5425e21ff8f8b Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <blogic@openwrt.org> | ||||
| Date: Mon, 15 Jul 2013 00:39:21 +0200 | ||||
| Subject: [PATCH 37/53] mtd: cfi cmdset 0002 force word write | ||||
|  | ||||
| --- | ||||
|  drivers/mtd/chips/cfi_cmdset_0002.c |    9 +++++++-- | ||||
|  1 file changed, 7 insertions(+), 2 deletions(-) | ||||
|  | ||||
| --- a/drivers/mtd/chips/cfi_cmdset_0002.c | ||||
| +++ b/drivers/mtd/chips/cfi_cmdset_0002.c | ||||
| @@ -40,7 +40,7 @@ | ||||
|  #include <linux/mtd/xip.h> | ||||
|   | ||||
|  #define AMD_BOOTLOC_BUG | ||||
| -#define FORCE_WORD_WRITE 0 | ||||
| +#define FORCE_WORD_WRITE 1 | ||||
|   | ||||
|  #define MAX_WORD_RETRIES 3 | ||||
|   | ||||
| @@ -51,7 +51,9 @@ | ||||
|   | ||||
|  static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); | ||||
|  static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); | ||||
| +#if !FORCE_WORD_WRITE | ||||
|  static int cfi_amdstd_write_buffers(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); | ||||
| +#endif | ||||
|  static int cfi_amdstd_erase_chip(struct mtd_info *, struct erase_info *); | ||||
|  static int cfi_amdstd_erase_varsize(struct mtd_info *, struct erase_info *); | ||||
|  static void cfi_amdstd_sync (struct mtd_info *); | ||||
| @@ -202,6 +204,7 @@ static void fixup_amd_bootblock(struct m | ||||
|  } | ||||
|  #endif | ||||
|   | ||||
| +#if !FORCE_WORD_WRITE | ||||
|  static void fixup_use_write_buffers(struct mtd_info *mtd) | ||||
|  { | ||||
|  	struct map_info *map = mtd->priv; | ||||
| @@ -211,6 +214,7 @@ static void fixup_use_write_buffers(stru | ||||
|  		mtd->_write = cfi_amdstd_write_buffers; | ||||
|  	} | ||||
|  } | ||||
| +#endif /* !FORCE_WORD_WRITE */ | ||||
|   | ||||
|  /* Atmel chips don't use the same PRI format as AMD chips */ | ||||
|  static void fixup_convert_atmel_pri(struct mtd_info *mtd) | ||||
| @@ -1787,6 +1791,7 @@ static int cfi_amdstd_write_words(struct | ||||
|  /* | ||||
|   * FIXME: interleaved mode not tested, and probably not supported! | ||||
|   */ | ||||
| +#if !FORCE_WORD_WRITE | ||||
|  static int __xipram do_write_buffer(struct map_info *map, struct flchip *chip, | ||||
|  				    unsigned long adr, const u_char *buf, | ||||
|  				    int len) | ||||
| @@ -1915,7 +1920,6 @@ static int __xipram do_write_buffer(stru | ||||
|  	return ret; | ||||
|  } | ||||
|   | ||||
| - | ||||
|  static int cfi_amdstd_write_buffers(struct mtd_info *mtd, loff_t to, size_t len, | ||||
|  				    size_t *retlen, const u_char *buf) | ||||
|  { | ||||
| @@ -1990,6 +1994,7 @@ static int cfi_amdstd_write_buffers(stru | ||||
|   | ||||
|  	return 0; | ||||
|  } | ||||
| +#endif /* !FORCE_WORD_WRITE */ | ||||
|   | ||||
|  /* | ||||
|   * Wait for the flash chip to become ready to write data | ||||
| @@ -0,0 +1,44 @@ | ||||
| From da6015e7f19d749f135f7ac55c4ec47b06faa868 Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <blogic@openwrt.org> | ||||
| Date: Fri, 9 Aug 2013 20:12:59 +0200 | ||||
| Subject: [PATCH 41/53] DT: Add documentation for spi-rt2880 | ||||
|  | ||||
| Describe the SPI master found on the MIPS based Ralink RT2880 SoC. | ||||
|  | ||||
| Signed-off-by: John Crispin <blogic@openwrt.org> | ||||
| --- | ||||
|  .../devicetree/bindings/spi/spi-rt2880.txt         |   28 ++++++++++++++++++++ | ||||
|  1 file changed, 28 insertions(+) | ||||
|  create mode 100644 Documentation/devicetree/bindings/spi/spi-rt2880.txt | ||||
|  | ||||
| --- /dev/null | ||||
| +++ b/Documentation/devicetree/bindings/spi/spi-rt2880.txt | ||||
| @@ -0,0 +1,28 @@ | ||||
| +Ralink SoC RT2880 SPI master controller. | ||||
| + | ||||
| +This SPI controller is found on most wireless SoCs made by ralink. | ||||
| + | ||||
| +Required properties: | ||||
| +- compatible : "ralink,rt2880-spi" | ||||
| +- reg : The register base for the controller. | ||||
| +- #address-cells : <1>, as required by generic SPI binding. | ||||
| +- #size-cells : <0>, also as required by generic SPI binding. | ||||
| + | ||||
| +Child nodes as per the generic SPI binding. | ||||
| + | ||||
| +Example: | ||||
| + | ||||
| +	spi@b00 { | ||||
| +		compatible = "ralink,rt2880-spi"; | ||||
| +		reg = <0xb00 0x100>; | ||||
| + | ||||
| +		#address-cells = <1>; | ||||
| +		#size-cells = <0>; | ||||
| + | ||||
| +		m25p80@0 { | ||||
| +			compatible = "m25p80"; | ||||
| +			reg = <0>; | ||||
| +			spi-max-frequency = <10000000>; | ||||
| +		}; | ||||
| +	}; | ||||
| + | ||||
| @@ -0,0 +1,574 @@ | ||||
| From 683af4ebb91a1600df1946ac4769d916b8a1be65 Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <blogic@openwrt.org> | ||||
| Date: Sun, 27 Jul 2014 11:15:12 +0100 | ||||
| Subject: [PATCH 42/53] SPI: ralink: add Ralink SoC spi driver | ||||
|  | ||||
| Add the driver needed to make SPI work on Ralink SoC. | ||||
|  | ||||
| Signed-off-by: Gabor Juhos <juhosg@openwrt.org> | ||||
| Acked-by: John Crispin <blogic@openwrt.org> | ||||
| --- | ||||
|  drivers/spi/Kconfig      |    6 + | ||||
|  drivers/spi/Makefile     |    1 + | ||||
|  drivers/spi/spi-rt2880.c |  530 ++++++++++++++++++++++++++++++++++++++++++++++ | ||||
|  3 files changed, 537 insertions(+) | ||||
|  create mode 100644 drivers/spi/spi-rt2880.c | ||||
|  | ||||
| --- a/drivers/spi/Kconfig | ||||
| +++ b/drivers/spi/Kconfig | ||||
| @@ -533,6 +533,12 @@ config SPI_QUP | ||||
|  	  This driver can also be built as a module.  If so, the module | ||||
|  	  will be called spi_qup. | ||||
|   | ||||
| +config SPI_RT2880 | ||||
| +	tristate "Ralink RT288x SPI Controller" | ||||
| +	depends on RALINK | ||||
| +	help | ||||
| +	  This selects a driver for the Ralink RT288x/RT305x SPI Controller. | ||||
| + | ||||
|  config SPI_S3C24XX | ||||
|  	tristate "Samsung S3C24XX series SPI" | ||||
|  	depends on ARCH_S3C24XX | ||||
| --- a/drivers/spi/Makefile | ||||
| +++ b/drivers/spi/Makefile | ||||
| @@ -76,6 +76,7 @@ obj-$(CONFIG_SPI_QUP)			+= spi-qup.o | ||||
|  obj-$(CONFIG_SPI_ROCKCHIP)		+= spi-rockchip.o | ||||
|  obj-$(CONFIG_SPI_RB4XX)			+= spi-rb4xx.o | ||||
|  obj-$(CONFIG_SPI_RSPI)			+= spi-rspi.o | ||||
| +obj-$(CONFIG_SPI_RT2880)		+= spi-rt2880.o | ||||
|  obj-$(CONFIG_SPI_S3C24XX)		+= spi-s3c24xx-hw.o | ||||
|  spi-s3c24xx-hw-y			:= spi-s3c24xx.o | ||||
|  spi-s3c24xx-hw-$(CONFIG_SPI_S3C24XX_FIQ) += spi-s3c24xx-fiq.o | ||||
| --- /dev/null | ||||
| +++ b/drivers/spi/spi-rt2880.c | ||||
| @@ -0,0 +1,530 @@ | ||||
| +/* | ||||
| + * spi-rt2880.c -- Ralink RT288x/RT305x SPI controller driver | ||||
| + * | ||||
| + * Copyright (C) 2011 Sergiy <piratfm@gmail.com> | ||||
| + * Copyright (C) 2011-2013 Gabor Juhos <juhosg@openwrt.org> | ||||
| + * | ||||
| + * Some parts are based on spi-orion.c: | ||||
| + *   Author: Shadi Ammouri <shadi@marvell.com> | ||||
| + *   Copyright (C) 2007-2008 Marvell Ltd. | ||||
| + * | ||||
| + * This program is free software; you can redistribute it and/or modify | ||||
| + * it under the terms of the GNU General Public License version 2 as | ||||
| + * published by the Free Software Foundation. | ||||
| + */ | ||||
| + | ||||
| +#include <linux/init.h> | ||||
| +#include <linux/module.h> | ||||
| +#include <linux/clk.h> | ||||
| +#include <linux/err.h> | ||||
| +#include <linux/delay.h> | ||||
| +#include <linux/io.h> | ||||
| +#include <linux/reset.h> | ||||
| +#include <linux/spi/spi.h> | ||||
| +#include <linux/platform_device.h> | ||||
| +#include <linux/gpio.h> | ||||
| + | ||||
| +#define DRIVER_NAME			"spi-rt2880" | ||||
| + | ||||
| +#define RAMIPS_SPI_STAT			0x00 | ||||
| +#define RAMIPS_SPI_CFG			0x10 | ||||
| +#define RAMIPS_SPI_CTL			0x14 | ||||
| +#define RAMIPS_SPI_DATA			0x20 | ||||
| +#define RAMIPS_SPI_ADDR			0x24 | ||||
| +#define RAMIPS_SPI_BS			0x28 | ||||
| +#define RAMIPS_SPI_USER			0x2C | ||||
| +#define RAMIPS_SPI_TXFIFO		0x30 | ||||
| +#define RAMIPS_SPI_RXFIFO		0x34 | ||||
| +#define RAMIPS_SPI_FIFO_STAT		0x38 | ||||
| +#define RAMIPS_SPI_MODE			0x3C | ||||
| +#define RAMIPS_SPI_DEV_OFFSET		0x40 | ||||
| +#define RAMIPS_SPI_DMA			0x80 | ||||
| +#define RAMIPS_SPI_DMASTAT		0x84 | ||||
| +#define RAMIPS_SPI_ARBITER		0xF0 | ||||
| + | ||||
| +/* SPISTAT register bit field */ | ||||
| +#define SPISTAT_BUSY			BIT(0) | ||||
| + | ||||
| +/* SPICFG register bit field */ | ||||
| +#define SPICFG_ADDRMODE			BIT(12) | ||||
| +#define SPICFG_RXENVDIS			BIT(11) | ||||
| +#define SPICFG_RXCAP			BIT(10) | ||||
| +#define SPICFG_SPIENMODE		BIT(9) | ||||
| +#define SPICFG_MSBFIRST			BIT(8) | ||||
| +#define SPICFG_SPICLKPOL		BIT(6) | ||||
| +#define SPICFG_RXCLKEDGE_FALLING	BIT(5) | ||||
| +#define SPICFG_TXCLKEDGE_FALLING	BIT(4) | ||||
| +#define SPICFG_HIZSPI			BIT(3) | ||||
| +#define SPICFG_SPICLK_PRESCALE_MASK	0x7 | ||||
| +#define SPICFG_SPICLK_DIV2		0 | ||||
| +#define SPICFG_SPICLK_DIV4		1 | ||||
| +#define SPICFG_SPICLK_DIV8		2 | ||||
| +#define SPICFG_SPICLK_DIV16		3 | ||||
| +#define SPICFG_SPICLK_DIV32		4 | ||||
| +#define SPICFG_SPICLK_DIV64		5 | ||||
| +#define SPICFG_SPICLK_DIV128		6 | ||||
| +#define SPICFG_SPICLK_DISABLE		7 | ||||
| + | ||||
| +/* SPICTL register bit field */ | ||||
| +#define SPICTL_START			BIT(4) | ||||
| +#define SPICTL_HIZSDO			BIT(3) | ||||
| +#define SPICTL_STARTWR			BIT(2) | ||||
| +#define SPICTL_STARTRD			BIT(1) | ||||
| +#define SPICTL_SPIENA			BIT(0) | ||||
| + | ||||
| +/* SPIUSER register bit field */ | ||||
| +#define SPIUSER_USERMODE		BIT(21) | ||||
| +#define SPIUSER_INSTR_PHASE		BIT(20) | ||||
| +#define SPIUSER_ADDR_PHASE_MASK		0x7 | ||||
| +#define SPIUSER_ADDR_PHASE_OFFSET	17 | ||||
| +#define SPIUSER_MODE_PHASE		BIT(16) | ||||
| +#define SPIUSER_DUMMY_PHASE_MASK	0x3 | ||||
| +#define SPIUSER_DUMMY_PHASE_OFFSET	14 | ||||
| +#define SPIUSER_DATA_PHASE_MASK		0x3 | ||||
| +#define SPIUSER_DATA_PHASE_OFFSET	12 | ||||
| +#define SPIUSER_DATA_READ		(BIT(0) << SPIUSER_DATA_PHASE_OFFSET) | ||||
| +#define SPIUSER_DATA_WRITE		(BIT(1) << SPIUSER_DATA_PHASE_OFFSET) | ||||
| +#define SPIUSER_ADDR_TYPE_OFFSET	9 | ||||
| +#define SPIUSER_MODE_TYPE_OFFSET	6 | ||||
| +#define SPIUSER_DUMMY_TYPE_OFFSET	3 | ||||
| +#define SPIUSER_DATA_TYPE_OFFSET	0 | ||||
| +#define SPIUSER_TRANSFER_MASK		0x7 | ||||
| +#define SPIUSER_TRANSFER_SINGLE		BIT(0) | ||||
| +#define SPIUSER_TRANSFER_DUAL		BIT(1) | ||||
| +#define SPIUSER_TRANSFER_QUAD		BIT(2) | ||||
| + | ||||
| +#define SPIUSER_TRANSFER_TYPE(type) ( \ | ||||
| +	(type << SPIUSER_ADDR_TYPE_OFFSET) | \ | ||||
| +	(type << SPIUSER_MODE_TYPE_OFFSET) | \ | ||||
| +	(type << SPIUSER_DUMMY_TYPE_OFFSET) | \ | ||||
| +	(type << SPIUSER_DATA_TYPE_OFFSET) \ | ||||
| +) | ||||
| + | ||||
| +/* SPIFIFOSTAT register bit field */ | ||||
| +#define SPIFIFOSTAT_TXEMPTY		BIT(19) | ||||
| +#define SPIFIFOSTAT_RXEMPTY		BIT(18) | ||||
| +#define SPIFIFOSTAT_TXFULL		BIT(17) | ||||
| +#define SPIFIFOSTAT_RXFULL		BIT(16) | ||||
| +#define SPIFIFOSTAT_FIFO_MASK		0xff | ||||
| +#define SPIFIFOSTAT_TX_OFFSET		8 | ||||
| +#define SPIFIFOSTAT_RX_OFFSET		0 | ||||
| + | ||||
| +#define SPI_FIFO_DEPTH			16 | ||||
| + | ||||
| +/* SPIMODE register bit field */ | ||||
| +#define SPIMODE_MODE_OFFSET		24 | ||||
| +#define SPIMODE_DUMMY_OFFSET		0 | ||||
| + | ||||
| +/* SPIARB register bit field */ | ||||
| +#define SPICTL_ARB_EN			BIT(31) | ||||
| +#define SPICTL_CSCTL1			BIT(16) | ||||
| +#define SPI1_POR			BIT(1) | ||||
| +#define SPI0_POR			BIT(0) | ||||
| + | ||||
| +#define RT2880_SPI_MODE_BITS	(SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | \ | ||||
| +		SPI_CS_HIGH) | ||||
| + | ||||
| +static atomic_t hw_reset_count = ATOMIC_INIT(0); | ||||
| + | ||||
| +struct rt2880_spi { | ||||
| +	struct spi_master	*master; | ||||
| +	void __iomem		*base; | ||||
| +	u32			speed; | ||||
| +	u16			wait_loops; | ||||
| +	u16			mode; | ||||
| +	struct clk		*clk; | ||||
| +}; | ||||
| + | ||||
| +static inline struct rt2880_spi *spidev_to_rt2880_spi(struct spi_device *spi) | ||||
| +{ | ||||
| +	return spi_master_get_devdata(spi->master); | ||||
| +} | ||||
| + | ||||
| +static inline u32 rt2880_spi_read(struct rt2880_spi *rs, u32 reg) | ||||
| +{ | ||||
| +	return ioread32(rs->base + reg); | ||||
| +} | ||||
| + | ||||
| +static inline void rt2880_spi_write(struct rt2880_spi *rs, u32 reg, | ||||
| +		const u32 val) | ||||
| +{ | ||||
| +	iowrite32(val, rs->base + reg); | ||||
| +} | ||||
| + | ||||
| +static inline void rt2880_spi_setbits(struct rt2880_spi *rs, u32 reg, u32 mask) | ||||
| +{ | ||||
| +	void __iomem *addr = rs->base + reg; | ||||
| + | ||||
| +	iowrite32((ioread32(addr) | mask), addr); | ||||
| +} | ||||
| + | ||||
| +static inline void rt2880_spi_clrbits(struct rt2880_spi *rs, u32 reg, u32 mask) | ||||
| +{ | ||||
| +	void __iomem *addr = rs->base + reg; | ||||
| + | ||||
| +	iowrite32((ioread32(addr) & ~mask), addr); | ||||
| +} | ||||
| + | ||||
| +static u32 rt2880_spi_baudrate_get(struct spi_device *spi, unsigned int speed) | ||||
| +{ | ||||
| +	struct rt2880_spi *rs = spidev_to_rt2880_spi(spi); | ||||
| +	u32 rate; | ||||
| +	u32 prescale; | ||||
| + | ||||
| +	/* | ||||
| +	 * the supported rates are: 2, 4, 8, ... 128 | ||||
| +	 * round up as we look for equal or less speed | ||||
| +	 */ | ||||
| +	rate = DIV_ROUND_UP(clk_get_rate(rs->clk), speed); | ||||
| +	rate = roundup_pow_of_two(rate); | ||||
| + | ||||
| +	/* Convert the rate to SPI clock divisor value.	*/ | ||||
| +	prescale = ilog2(rate / 2); | ||||
| + | ||||
| +	/* some tolerance. double and add 100 */ | ||||
| +	rs->wait_loops = (8 * HZ * loops_per_jiffy) / | ||||
| +		(clk_get_rate(rs->clk) / rate); | ||||
| +	rs->wait_loops = (rs->wait_loops << 1) + 100; | ||||
| +	rs->speed = speed; | ||||
| + | ||||
| +	dev_dbg(&spi->dev, "speed: %lu/%u, rate: %u, prescal: %u, loops: %hu\n", | ||||
| +			clk_get_rate(rs->clk) / rate, speed, rate, prescale, | ||||
| +			rs->wait_loops); | ||||
| + | ||||
| +	return prescale; | ||||
| +} | ||||
| + | ||||
| +static u32 get_arbiter_offset(struct spi_master *master) | ||||
| +{ | ||||
| +	u32 offset; | ||||
| + | ||||
| +	offset = RAMIPS_SPI_ARBITER; | ||||
| +	if (master->bus_num == 1) | ||||
| +		offset -= RAMIPS_SPI_DEV_OFFSET; | ||||
| + | ||||
| +	return offset; | ||||
| +} | ||||
| + | ||||
| +static void rt2880_spi_set_cs(struct spi_device *spi, bool enable) | ||||
| +{ | ||||
| +	struct rt2880_spi *rs = spidev_to_rt2880_spi(spi); | ||||
| + | ||||
| +	if (enable) | ||||
| +		rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA); | ||||
| +	else | ||||
| +		rt2880_spi_clrbits(rs, RAMIPS_SPI_CTL, SPICTL_SPIENA); | ||||
| +} | ||||
| + | ||||
| +static int rt2880_spi_wait_ready(struct rt2880_spi *rs, int len) | ||||
| +{ | ||||
| +	int loop = rs->wait_loops * len; | ||||
| + | ||||
| +	while ((rt2880_spi_read(rs, RAMIPS_SPI_STAT) & SPISTAT_BUSY) && --loop) | ||||
| +		cpu_relax(); | ||||
| + | ||||
| +	if (loop) | ||||
| +		return 0; | ||||
| + | ||||
| +	return -ETIMEDOUT; | ||||
| +} | ||||
| + | ||||
| +static void rt2880_dump_reg(struct spi_master *master) | ||||
| +{ | ||||
| +	struct rt2880_spi *rs = spi_master_get_devdata(master); | ||||
| + | ||||
| +	dev_dbg(&master->dev, "stat: %08x, cfg: %08x, ctl: %08x, " \ | ||||
| +			"data: %08x, arb: %08x\n", | ||||
| +			rt2880_spi_read(rs, RAMIPS_SPI_STAT), | ||||
| +			rt2880_spi_read(rs, RAMIPS_SPI_CFG), | ||||
| +			rt2880_spi_read(rs, RAMIPS_SPI_CTL), | ||||
| +			rt2880_spi_read(rs, RAMIPS_SPI_DATA), | ||||
| +			rt2880_spi_read(rs, get_arbiter_offset(master))); | ||||
| +} | ||||
| + | ||||
| +static int rt2880_spi_transfer_one(struct spi_master *master, | ||||
| +		struct spi_device *spi, struct spi_transfer *xfer) | ||||
| +{ | ||||
| +	struct rt2880_spi *rs = spi_master_get_devdata(master); | ||||
| +	unsigned len; | ||||
| +	const u8 *tx = xfer->tx_buf; | ||||
| +	u8 *rx = xfer->rx_buf; | ||||
| +	int err = 0; | ||||
| + | ||||
| +	/* change clock speed  */ | ||||
| +	if (unlikely(rs->speed != xfer->speed_hz)) { | ||||
| +		u32 reg; | ||||
| +		reg = rt2880_spi_read(rs, RAMIPS_SPI_CFG); | ||||
| +		reg &= ~SPICFG_SPICLK_PRESCALE_MASK; | ||||
| +		reg |= rt2880_spi_baudrate_get(spi, xfer->speed_hz); | ||||
| +		rt2880_spi_write(rs, RAMIPS_SPI_CFG, reg); | ||||
| +	} | ||||
| + | ||||
| +	if (tx) { | ||||
| +		len = xfer->len; | ||||
| +		while (len-- > 0) { | ||||
| +			rt2880_spi_write(rs, RAMIPS_SPI_DATA, *tx++); | ||||
| +			rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_STARTWR); | ||||
| +			err = rt2880_spi_wait_ready(rs, 1); | ||||
| +			if (err) { | ||||
| +				dev_err(&spi->dev, "TX failed, err=%d\n", err); | ||||
| +				goto out; | ||||
| +			} | ||||
| +		} | ||||
| +	} | ||||
| + | ||||
| +	if (rx) { | ||||
| +		len = xfer->len; | ||||
| +		while (len-- > 0) { | ||||
| +			rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_STARTRD); | ||||
| +			err = rt2880_spi_wait_ready(rs, 1); | ||||
| +			if (err) { | ||||
| +				dev_err(&spi->dev, "RX failed, err=%d\n", err); | ||||
| +				goto out; | ||||
| +			} | ||||
| +			*rx++ = (u8) rt2880_spi_read(rs, RAMIPS_SPI_DATA); | ||||
| +		} | ||||
| +	} | ||||
| + | ||||
| +out: | ||||
| +	return err; | ||||
| +} | ||||
| + | ||||
| +/* copy from spi.c */ | ||||
| +static void spi_set_cs(struct spi_device *spi, bool enable) | ||||
| +{ | ||||
| +	if (spi->mode & SPI_CS_HIGH) | ||||
| +		enable = !enable; | ||||
| + | ||||
| +	if (spi->cs_gpio >= 0) | ||||
| +		gpio_set_value(spi->cs_gpio, !enable); | ||||
| +	else if (spi->master->set_cs) | ||||
| +		spi->master->set_cs(spi, !enable); | ||||
| +} | ||||
| + | ||||
| +static int rt2880_spi_setup(struct spi_device *spi) | ||||
| +{ | ||||
| +	struct spi_master *master = spi->master; | ||||
| +	struct rt2880_spi *rs = spi_master_get_devdata(master); | ||||
| +	u32 reg, old_reg, arbit_off; | ||||
| + | ||||
| +	if ((spi->max_speed_hz > master->max_speed_hz) || | ||||
| +			(spi->max_speed_hz < master->min_speed_hz)) { | ||||
| +		dev_err(&spi->dev, "invalide requested speed %d Hz\n", | ||||
| +				spi->max_speed_hz); | ||||
| +		return -EINVAL; | ||||
| +	} | ||||
| + | ||||
| +	if (!(master->bits_per_word_mask & | ||||
| +				BIT(spi->bits_per_word - 1))) { | ||||
| +		dev_err(&spi->dev, "invalide bits_per_word %d\n", | ||||
| +				spi->bits_per_word); | ||||
| +		return -EINVAL; | ||||
| +	} | ||||
| + | ||||
| +	/* the hardware seems can't work on mode0 force it to mode3 */ | ||||
| +	if ((spi->mode & (SPI_CPOL | SPI_CPHA)) == SPI_MODE_0) { | ||||
| +		dev_warn(&spi->dev, "force spi mode3\n"); | ||||
| +		spi->mode |= SPI_MODE_3; | ||||
| +	} | ||||
| + | ||||
| +	/* chip polarity */ | ||||
| +	arbit_off = get_arbiter_offset(master); | ||||
| +	reg = old_reg = rt2880_spi_read(rs, arbit_off); | ||||
| +	if (spi->mode & SPI_CS_HIGH) { | ||||
| +		switch (master->bus_num) { | ||||
| +		case 1: | ||||
| +			reg |= SPI1_POR; | ||||
| +			break; | ||||
| +		default: | ||||
| +			reg |= SPI0_POR; | ||||
| +			break; | ||||
| +		} | ||||
| +	} else { | ||||
| +		switch (master->bus_num) { | ||||
| +		case 1: | ||||
| +			reg &= ~SPI1_POR; | ||||
| +			break; | ||||
| +		default: | ||||
| +			reg &= ~SPI0_POR; | ||||
| +			break; | ||||
| +		} | ||||
| +	} | ||||
| + | ||||
| +	/* enable spi1 */ | ||||
| +	if (master->bus_num == 1) | ||||
| +		reg |= SPICTL_ARB_EN; | ||||
| + | ||||
| +	if (reg != old_reg) | ||||
| +		rt2880_spi_write(rs, arbit_off, reg); | ||||
| + | ||||
| +	/* deselected the spi device */ | ||||
| +	spi_set_cs(spi, false); | ||||
| + | ||||
| +	rt2880_dump_reg(master); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static int rt2880_spi_prepare_message(struct spi_master *master, | ||||
| +		struct spi_message *msg) | ||||
| +{ | ||||
| +	struct rt2880_spi *rs = spi_master_get_devdata(master); | ||||
| +	struct spi_device *spi = msg->spi; | ||||
| +	u32 reg; | ||||
| + | ||||
| +	if ((rs->mode == spi->mode) && (rs->speed == spi->max_speed_hz)) | ||||
| +		return 0; | ||||
| + | ||||
| +#if 0 | ||||
| +	/* set spido to tri-state */ | ||||
| +	rt2880_spi_setbits(rs, RAMIPS_SPI_CTL, SPICTL_HIZSDO); | ||||
| +#endif | ||||
| + | ||||
| +	reg = rt2880_spi_read(rs, RAMIPS_SPI_CFG); | ||||
| + | ||||
| +	reg &= ~(SPICFG_MSBFIRST | SPICFG_SPICLKPOL | | ||||
| +			SPICFG_RXCLKEDGE_FALLING | | ||||
| +			SPICFG_TXCLKEDGE_FALLING | | ||||
| +			SPICFG_SPICLK_PRESCALE_MASK); | ||||
| + | ||||
| +	/* MSB */ | ||||
| +	if (!(spi->mode & SPI_LSB_FIRST)) | ||||
| +		reg |= SPICFG_MSBFIRST; | ||||
| + | ||||
| +	/* spi mode */ | ||||
| +	switch (spi->mode & (SPI_CPOL | SPI_CPHA)) { | ||||
| +	case SPI_MODE_0: | ||||
| +		reg |= SPICFG_TXCLKEDGE_FALLING; | ||||
| +		break; | ||||
| +	case SPI_MODE_1: | ||||
| +		reg |= SPICFG_RXCLKEDGE_FALLING; | ||||
| +		break; | ||||
| +	case SPI_MODE_2: | ||||
| +		reg |= SPICFG_SPICLKPOL | SPICFG_RXCLKEDGE_FALLING; | ||||
| +		break; | ||||
| +	case SPI_MODE_3: | ||||
| +		reg |= SPICFG_SPICLKPOL | SPICFG_TXCLKEDGE_FALLING; | ||||
| +		break; | ||||
| +	} | ||||
| +	rs->mode = spi->mode; | ||||
| + | ||||
| +#if 0 | ||||
| +	/* set spiclk and spiena to tri-state */ | ||||
| +	reg |= SPICFG_HIZSPI; | ||||
| +#endif | ||||
| + | ||||
| +	/* clock divide */ | ||||
| +	reg |= rt2880_spi_baudrate_get(spi, spi->max_speed_hz); | ||||
| + | ||||
| +	rt2880_spi_write(rs, RAMIPS_SPI_CFG, reg); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static int rt2880_spi_probe(struct platform_device *pdev) | ||||
| +{ | ||||
| +	struct spi_master *master; | ||||
| +	struct rt2880_spi *rs; | ||||
| +	void __iomem *base; | ||||
| +	struct resource *r; | ||||
| +	struct clk *clk; | ||||
| +	int ret; | ||||
| + | ||||
| +	r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||||
| +	base = devm_ioremap_resource(&pdev->dev, r); | ||||
| +	if (IS_ERR(base)) | ||||
| +		return PTR_ERR(base); | ||||
| + | ||||
| +	clk = devm_clk_get(&pdev->dev, NULL); | ||||
| +	if (IS_ERR(clk)) { | ||||
| +		dev_err(&pdev->dev, "unable to get SYS clock\n"); | ||||
| +		return PTR_ERR(clk); | ||||
| +	} | ||||
| + | ||||
| +	ret = clk_prepare_enable(clk); | ||||
| +	if (ret) | ||||
| +		goto err_clk; | ||||
| + | ||||
| +	master = spi_alloc_master(&pdev->dev, sizeof(*rs)); | ||||
| +	if (master == NULL) { | ||||
| +		dev_dbg(&pdev->dev, "master allocation failed\n"); | ||||
| +		ret = -ENOMEM; | ||||
| +		goto err_clk; | ||||
| +	} | ||||
| + | ||||
| +	master->dev.of_node = pdev->dev.of_node; | ||||
| +	master->mode_bits = RT2880_SPI_MODE_BITS; | ||||
| +	master->bits_per_word_mask = SPI_BPW_MASK(8); | ||||
| +	master->min_speed_hz = clk_get_rate(clk) / 128; | ||||
| +	master->max_speed_hz = clk_get_rate(clk) / 2; | ||||
| +	master->flags = SPI_MASTER_HALF_DUPLEX; | ||||
| +	master->setup = rt2880_spi_setup; | ||||
| +	master->prepare_message = rt2880_spi_prepare_message; | ||||
| +	master->set_cs = rt2880_spi_set_cs; | ||||
| +	master->transfer_one = rt2880_spi_transfer_one, | ||||
| + | ||||
| +	dev_set_drvdata(&pdev->dev, master); | ||||
| + | ||||
| +	rs = spi_master_get_devdata(master); | ||||
| +	rs->master = master; | ||||
| +	rs->base = base; | ||||
| +	rs->clk = clk; | ||||
| + | ||||
| +	if (atomic_inc_return(&hw_reset_count) == 1) | ||||
| +		device_reset(&pdev->dev); | ||||
| + | ||||
| +	ret = devm_spi_register_master(&pdev->dev, master); | ||||
| +	if (ret < 0) { | ||||
| +		dev_err(&pdev->dev, "devm_spi_register_master error.\n"); | ||||
| +		goto err_master; | ||||
| +	} | ||||
| + | ||||
| +	return ret; | ||||
| + | ||||
| +err_master: | ||||
| +	spi_master_put(master); | ||||
| +	kfree(master); | ||||
| +err_clk: | ||||
| +	clk_disable_unprepare(clk); | ||||
| + | ||||
| +	return ret; | ||||
| +} | ||||
| + | ||||
| +static int rt2880_spi_remove(struct platform_device *pdev) | ||||
| +{ | ||||
| +	struct spi_master *master; | ||||
| +	struct rt2880_spi *rs; | ||||
| + | ||||
| +	master = dev_get_drvdata(&pdev->dev); | ||||
| +	rs = spi_master_get_devdata(master); | ||||
| + | ||||
| +	clk_disable_unprepare(rs->clk); | ||||
| +	atomic_dec(&hw_reset_count); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +MODULE_ALIAS("platform:" DRIVER_NAME); | ||||
| + | ||||
| +static const struct of_device_id rt2880_spi_match[] = { | ||||
| +	{ .compatible = "ralink,rt2880-spi" }, | ||||
| +	{}, | ||||
| +}; | ||||
| +MODULE_DEVICE_TABLE(of, rt2880_spi_match); | ||||
| + | ||||
| +static struct platform_driver rt2880_spi_driver = { | ||||
| +	.driver = { | ||||
| +		.name = DRIVER_NAME, | ||||
| +		.owner = THIS_MODULE, | ||||
| +		.of_match_table = rt2880_spi_match, | ||||
| +	}, | ||||
| +	.probe = rt2880_spi_probe, | ||||
| +	.remove = rt2880_spi_remove, | ||||
| +}; | ||||
| + | ||||
| +module_platform_driver(rt2880_spi_driver); | ||||
| + | ||||
| +MODULE_DESCRIPTION("Ralink SPI driver"); | ||||
| +MODULE_AUTHOR("Sergiy <piratfm@gmail.com>"); | ||||
| +MODULE_AUTHOR("Gabor Juhos <juhosg@openwrt.org>"); | ||||
| +MODULE_LICENSE("GPL"); | ||||
| @@ -0,0 +1,524 @@ | ||||
| From 87a5fcd57c577cd94b5b080deb98885077c13a42 Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <blogic@openwrt.org> | ||||
| Date: Sun, 27 Jul 2014 09:49:07 +0100 | ||||
| Subject: [PATCH 43/53] spi: add mt7621 support | ||||
|  | ||||
| Signed-off-by: John Crispin <blogic@openwrt.org> | ||||
| --- | ||||
|  drivers/spi/Kconfig      |    6 + | ||||
|  drivers/spi/Makefile     |    1 + | ||||
|  drivers/spi/spi-mt7621.c |  480 ++++++++++++++++++++++++++++++++++++++++++++++ | ||||
|  3 files changed, 487 insertions(+) | ||||
|  create mode 100644 drivers/spi/spi-mt7621.c | ||||
|  | ||||
| --- a/drivers/spi/Kconfig | ||||
| +++ b/drivers/spi/Kconfig | ||||
| @@ -539,6 +539,12 @@ config SPI_RT2880 | ||||
|  	help | ||||
|  	  This selects a driver for the Ralink RT288x/RT305x SPI Controller. | ||||
|   | ||||
| +config SPI_MT7621 | ||||
| +	tristate "MediaTek MT7621 SPI Controller" | ||||
| +	depends on RALINK | ||||
| +	help | ||||
| +	  This selects a driver for the MediaTek MT7621 SPI Controller. | ||||
| + | ||||
|  config SPI_S3C24XX | ||||
|  	tristate "Samsung S3C24XX series SPI" | ||||
|  	depends on ARCH_S3C24XX | ||||
| --- a/drivers/spi/Makefile | ||||
| +++ b/drivers/spi/Makefile | ||||
| @@ -55,6 +55,7 @@ obj-$(CONFIG_SPI_MPC512x_PSC)		+= spi-mp | ||||
|  obj-$(CONFIG_SPI_MPC52xx_PSC)		+= spi-mpc52xx-psc.o | ||||
|  obj-$(CONFIG_SPI_MPC52xx)		+= spi-mpc52xx.o | ||||
|  obj-$(CONFIG_SPI_MT65XX)                += spi-mt65xx.o | ||||
| +obj-$(CONFIG_SPI_MT7621)		+= spi-mt7621.o | ||||
|  obj-$(CONFIG_SPI_MXS)			+= spi-mxs.o | ||||
|  obj-$(CONFIG_SPI_NUC900)		+= spi-nuc900.o | ||||
|  obj-$(CONFIG_SPI_OC_TINY)		+= spi-oc-tiny.o | ||||
| --- /dev/null | ||||
| +++ b/drivers/spi/spi-mt7621.c | ||||
| @@ -0,0 +1,483 @@ | ||||
| +/* | ||||
| + * spi-mt7621.c -- MediaTek MT7621 SPI controller driver | ||||
| + * | ||||
| + * Copyright (C) 2011 Sergiy <piratfm@gmail.com> | ||||
| + * Copyright (C) 2011-2013 Gabor Juhos <juhosg@openwrt.org> | ||||
| + * Copyright (C) 2014-2015 Felix Fietkau <nbd@nbd.name> | ||||
| + * | ||||
| + * Some parts are based on spi-orion.c: | ||||
| + *   Author: Shadi Ammouri <shadi@marvell.com> | ||||
| + *   Copyright (C) 2007-2008 Marvell Ltd. | ||||
| + * | ||||
| + * This program is free software; you can redistribute it and/or modify | ||||
| + * it under the terms of the GNU General Public License version 2 as | ||||
| + * published by the Free Software Foundation. | ||||
| + */ | ||||
| + | ||||
| +#include <linux/init.h> | ||||
| +#include <linux/module.h> | ||||
| +#include <linux/clk.h> | ||||
| +#include <linux/err.h> | ||||
| +#include <linux/delay.h> | ||||
| +#include <linux/io.h> | ||||
| +#include <linux/reset.h> | ||||
| +#include <linux/spi/spi.h> | ||||
| +#include <linux/of_device.h> | ||||
| +#include <linux/platform_device.h> | ||||
| +#include <linux/swab.h> | ||||
| + | ||||
| +#include <ralink_regs.h> | ||||
| + | ||||
| +#define SPI_BPW_MASK(bits) BIT((bits) - 1) | ||||
| + | ||||
| +#define DRIVER_NAME			"spi-mt7621" | ||||
| +/* in usec */ | ||||
| +#define RALINK_SPI_WAIT_MAX_LOOP	2000 | ||||
| + | ||||
| +/* SPISTAT register bit field */ | ||||
| +#define SPISTAT_BUSY			BIT(0) | ||||
| + | ||||
| +#define MT7621_SPI_TRANS	0x00 | ||||
| +#define SPITRANS_BUSY		BIT(16) | ||||
| + | ||||
| +#define MT7621_SPI_OPCODE	0x04 | ||||
| +#define MT7621_SPI_DATA0	0x08 | ||||
| +#define MT7621_SPI_DATA4	0x18 | ||||
| +#define SPI_CTL_TX_RX_CNT_MASK	0xff | ||||
| +#define SPI_CTL_START		BIT(8) | ||||
| + | ||||
| +#define MT7621_SPI_POLAR	0x38 | ||||
| +#define MT7621_SPI_MASTER	0x28 | ||||
| +#define MT7621_SPI_MOREBUF	0x2c | ||||
| +#define MT7621_SPI_SPACE	0x3c | ||||
| + | ||||
| +#define MT7621_CPHA		BIT(5) | ||||
| +#define MT7621_CPOL		BIT(4) | ||||
| +#define MT7621_LSB_FIRST	BIT(3) | ||||
| + | ||||
| +#define RT2880_SPI_MODE_BITS	(SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_CS_HIGH) | ||||
| + | ||||
| +struct mt7621_spi; | ||||
| + | ||||
| +struct mt7621_spi { | ||||
| +	struct spi_master	*master; | ||||
| +	void __iomem		*base; | ||||
| +	unsigned int		sys_freq; | ||||
| +	unsigned int		speed; | ||||
| +	struct clk		*clk; | ||||
| +	spinlock_t		lock; | ||||
| + | ||||
| +	struct mt7621_spi_ops	*ops; | ||||
| +}; | ||||
| + | ||||
| +static inline struct mt7621_spi *spidev_to_mt7621_spi(struct spi_device *spi) | ||||
| +{ | ||||
| +	return spi_master_get_devdata(spi->master); | ||||
| +} | ||||
| + | ||||
| +static inline u32 mt7621_spi_read(struct mt7621_spi *rs, u32 reg) | ||||
| +{ | ||||
| +	return ioread32(rs->base + reg); | ||||
| +} | ||||
| + | ||||
| +static inline void mt7621_spi_write(struct mt7621_spi *rs, u32 reg, u32 val) | ||||
| +{ | ||||
| +	iowrite32(val, rs->base + reg); | ||||
| +} | ||||
| + | ||||
| +static void mt7621_spi_reset(struct mt7621_spi *rs, int duplex) | ||||
| +{ | ||||
| +	u32 master = mt7621_spi_read(rs, MT7621_SPI_MASTER); | ||||
| + | ||||
| +	master |= 7 << 29; | ||||
| +	master |= 1 << 2; | ||||
| +	if (duplex) | ||||
| +		master |= 1 << 10; | ||||
| +	else | ||||
| +		master &= ~(1 << 10); | ||||
| + | ||||
| +	mt7621_spi_write(rs, MT7621_SPI_MASTER, master); | ||||
| +} | ||||
| + | ||||
| +static void mt7621_spi_set_cs(struct spi_device *spi, int enable) | ||||
| +{ | ||||
| +	struct mt7621_spi *rs = spidev_to_mt7621_spi(spi); | ||||
| +	int cs = spi->chip_select; | ||||
| +	u32 polar = 0; | ||||
| + | ||||
| +        mt7621_spi_reset(rs, cs); | ||||
| +	if (enable) | ||||
| +		polar = BIT(cs); | ||||
| +	mt7621_spi_write(rs, MT7621_SPI_POLAR, polar); | ||||
| +} | ||||
| + | ||||
| +static int mt7621_spi_prepare(struct spi_device *spi, unsigned int speed) | ||||
| +{ | ||||
| +	struct mt7621_spi *rs = spidev_to_mt7621_spi(spi); | ||||
| +	u32 rate; | ||||
| +	u32 reg; | ||||
| + | ||||
| +	dev_dbg(&spi->dev, "speed:%u\n", speed); | ||||
| + | ||||
| +	rate = DIV_ROUND_UP(rs->sys_freq, speed); | ||||
| +	dev_dbg(&spi->dev, "rate-1:%u\n", rate); | ||||
| + | ||||
| +	if (rate > 4097) | ||||
| +		return -EINVAL; | ||||
| + | ||||
| +	if (rate < 2) | ||||
| +		rate = 2; | ||||
| + | ||||
| +	reg = mt7621_spi_read(rs, MT7621_SPI_MASTER); | ||||
| +	reg &= ~(0xfff << 16); | ||||
| +	reg |= (rate - 2) << 16; | ||||
| +	rs->speed = speed; | ||||
| + | ||||
| +	reg &= ~MT7621_LSB_FIRST; | ||||
| +	if (spi->mode & SPI_LSB_FIRST) | ||||
| +		reg |= MT7621_LSB_FIRST; | ||||
| + | ||||
| +	reg &= ~(MT7621_CPHA | MT7621_CPOL); | ||||
| +	switch(spi->mode & (SPI_CPOL | SPI_CPHA)) { | ||||
| +		case SPI_MODE_0: | ||||
| +			break; | ||||
| +		case SPI_MODE_1: | ||||
| +			reg |= MT7621_CPHA; | ||||
| +			break; | ||||
| +		case SPI_MODE_2: | ||||
| +			reg |= MT7621_CPOL; | ||||
| +			break; | ||||
| +		case SPI_MODE_3: | ||||
| +			reg |= MT7621_CPOL | MT7621_CPHA; | ||||
| +			break; | ||||
| +	} | ||||
| +	mt7621_spi_write(rs, MT7621_SPI_MASTER, reg); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static inline int mt7621_spi_wait_till_ready(struct spi_device *spi) | ||||
| +{ | ||||
| +	struct mt7621_spi *rs = spidev_to_mt7621_spi(spi); | ||||
| +	int i; | ||||
| + | ||||
| +	for (i = 0; i < RALINK_SPI_WAIT_MAX_LOOP; i++) { | ||||
| +		u32 status; | ||||
| + | ||||
| +		status = mt7621_spi_read(rs, MT7621_SPI_TRANS); | ||||
| +		if ((status & SPITRANS_BUSY) == 0) { | ||||
| +			return 0; | ||||
| +		} | ||||
| +		cpu_relax(); | ||||
| +		udelay(1); | ||||
| +	} | ||||
| + | ||||
| +	return -ETIMEDOUT; | ||||
| +} | ||||
| + | ||||
| +static int mt7621_spi_transfer_half_duplex(struct spi_master *master, | ||||
| +					   struct spi_message *m) | ||||
| +{ | ||||
| +	struct mt7621_spi *rs = spi_master_get_devdata(master); | ||||
| +	struct spi_device *spi = m->spi; | ||||
| +	unsigned int speed = spi->max_speed_hz; | ||||
| +	struct spi_transfer *t = NULL; | ||||
| +	int status = 0; | ||||
| +	int i, len = 0; | ||||
| +	int rx_len = 0; | ||||
| +	u32 data[9] = { 0 }; | ||||
| +	u32 val; | ||||
| + | ||||
| +	mt7621_spi_wait_till_ready(spi); | ||||
| + | ||||
| +	list_for_each_entry(t, &m->transfers, transfer_list) { | ||||
| +		const u8 *buf = t->tx_buf; | ||||
| + | ||||
| +		if (t->rx_buf) | ||||
| +			rx_len += t->len; | ||||
| + | ||||
| +		if (!buf) | ||||
| +			continue; | ||||
| + | ||||
| +		if (t->speed_hz < speed) | ||||
| +			speed = t->speed_hz; | ||||
| + | ||||
| +		if (WARN_ON(len + t->len > 36)) { | ||||
| +			status = -EIO; | ||||
| +			goto msg_done; | ||||
| +		} | ||||
| + | ||||
| +		for (i = 0; i < t->len; i++, len++) | ||||
| +			data[len / 4] |= buf[i] << (8 * (len & 3)); | ||||
| +	} | ||||
| + | ||||
| +	if (WARN_ON(rx_len > 32)) { | ||||
| +		status = -EIO; | ||||
| +		goto msg_done; | ||||
| +	} | ||||
| + | ||||
| +	if (mt7621_spi_prepare(spi, speed)) { | ||||
| +		status = -EIO; | ||||
| +		goto msg_done; | ||||
| +	} | ||||
| +	data[0] = swab32(data[0]); | ||||
| +	if (len < 4) | ||||
| +		data[0] >>= (4 - len) * 8; | ||||
| + | ||||
| +	for (i = 0; i < len; i += 4) | ||||
| +		mt7621_spi_write(rs, MT7621_SPI_OPCODE + i, data[i / 4]); | ||||
| + | ||||
| +	val = (min_t(int, len, 4) * 8) << 24; | ||||
| +	if (len > 4) | ||||
| +		val |= (len - 4) * 8; | ||||
| +	val |= (rx_len * 8) << 12; | ||||
| +	mt7621_spi_write(rs, MT7621_SPI_MOREBUF, val); | ||||
| + | ||||
| +	mt7621_spi_set_cs(spi, 1); | ||||
| + | ||||
| +	val = mt7621_spi_read(rs, MT7621_SPI_TRANS); | ||||
| +	val |= SPI_CTL_START; | ||||
| +	mt7621_spi_write(rs, MT7621_SPI_TRANS, val); | ||||
| + | ||||
| +	mt7621_spi_wait_till_ready(spi); | ||||
| + | ||||
| +	mt7621_spi_set_cs(spi, 0); | ||||
| + | ||||
| +	for (i = 0; i < rx_len; i += 4) | ||||
| +		data[i / 4] = mt7621_spi_read(rs, MT7621_SPI_DATA0 + i); | ||||
| + | ||||
| +	m->actual_length = len + rx_len; | ||||
| + | ||||
| +	len = 0; | ||||
| +	list_for_each_entry(t, &m->transfers, transfer_list) { | ||||
| +		u8 *buf = t->rx_buf; | ||||
| + | ||||
| +		if (!buf) | ||||
| +			continue; | ||||
| + | ||||
| +		for (i = 0; i < t->len; i++, len++) | ||||
| +			buf[i] = data[len / 4] >> (8 * (len & 3)); | ||||
| +	} | ||||
| + | ||||
| +msg_done: | ||||
| +	m->status = status; | ||||
| +	spi_finalize_current_message(master); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static int mt7621_spi_transfer_full_duplex(struct spi_master *master, | ||||
| +					   struct spi_message *m) | ||||
| +{ | ||||
| +	struct mt7621_spi *rs = spi_master_get_devdata(master); | ||||
| +	struct spi_device *spi = m->spi; | ||||
| +	unsigned int speed = spi->max_speed_hz; | ||||
| +	struct spi_transfer *t = NULL; | ||||
| +	int status = 0; | ||||
| +	int i, len = 0; | ||||
| +	int rx_len = 0; | ||||
| +	u32 data[9] = { 0 }; | ||||
| +	u32 val = 0; | ||||
| + | ||||
| +	mt7621_spi_wait_till_ready(spi); | ||||
| + | ||||
| +	list_for_each_entry(t, &m->transfers, transfer_list) { | ||||
| +		const u8 *buf = t->tx_buf; | ||||
| + | ||||
| +		if (t->rx_buf) | ||||
| +			rx_len += t->len; | ||||
| + | ||||
| +		if (!buf) | ||||
| +			continue; | ||||
| + | ||||
| +		if (WARN_ON(len + t->len > 16)) { | ||||
| +			status = -EIO; | ||||
| +			goto msg_done; | ||||
| +		} | ||||
| + | ||||
| +		for (i = 0; i < t->len; i++, len++) | ||||
| +			data[len / 4] |= buf[i] << (8 * (len & 3)); | ||||
| +		if (speed > t->speed_hz) | ||||
| +			speed = t->speed_hz; | ||||
| +	} | ||||
| + | ||||
| +	if (WARN_ON(rx_len > 16)) { | ||||
| +		status = -EIO; | ||||
| +		goto msg_done; | ||||
| +	} | ||||
| + | ||||
| +	if (mt7621_spi_prepare(spi, speed)) { | ||||
| +		status = -EIO; | ||||
| +		goto msg_done; | ||||
| +	} | ||||
| + | ||||
| +	for (i = 0; i < len; i += 4) | ||||
| +		mt7621_spi_write(rs, MT7621_SPI_DATA0 + i, data[i / 4]); | ||||
| + | ||||
| +	val |= len * 8; | ||||
| +	val |= (rx_len * 8) << 12; | ||||
| +	mt7621_spi_write(rs, MT7621_SPI_MOREBUF, val); | ||||
| + | ||||
| +	mt7621_spi_set_cs(spi, 1); | ||||
| + | ||||
| +	val = mt7621_spi_read(rs, MT7621_SPI_TRANS); | ||||
| +	val |= SPI_CTL_START; | ||||
| +	mt7621_spi_write(rs, MT7621_SPI_TRANS, val); | ||||
| + | ||||
| +	mt7621_spi_wait_till_ready(spi); | ||||
| + | ||||
| +	mt7621_spi_set_cs(spi, 0); | ||||
| + | ||||
| +	for (i = 0; i < rx_len; i += 4) | ||||
| +		data[i / 4] = mt7621_spi_read(rs, MT7621_SPI_DATA4 + i); | ||||
| + | ||||
| +	m->actual_length = rx_len; | ||||
| + | ||||
| +	len = 0; | ||||
| +	list_for_each_entry(t, &m->transfers, transfer_list) { | ||||
| +		u8 *buf = t->rx_buf; | ||||
| + | ||||
| +		if (!buf) | ||||
| +			continue; | ||||
| + | ||||
| +		for (i = 0; i < t->len; i++, len++) | ||||
| +			buf[i] = data[len / 4] >> (8 * (len & 3)); | ||||
| +	} | ||||
| + | ||||
| +msg_done: | ||||
| +	m->status = status; | ||||
| +	spi_finalize_current_message(master); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static int mt7621_spi_transfer_one_message(struct spi_master *master, | ||||
| +					   struct spi_message *m) | ||||
| +{ | ||||
| +	struct spi_device *spi = m->spi; | ||||
| +	int cs = spi->chip_select; | ||||
| + | ||||
| +	if (cs) | ||||
| +		return mt7621_spi_transfer_full_duplex(master, m); | ||||
| +	return mt7621_spi_transfer_half_duplex(master, m); | ||||
| +} | ||||
| + | ||||
| +static int mt7621_spi_setup(struct spi_device *spi) | ||||
| +{ | ||||
| +	struct mt7621_spi *rs = spidev_to_mt7621_spi(spi); | ||||
| + | ||||
| +	if ((spi->max_speed_hz == 0) || | ||||
| +		(spi->max_speed_hz > (rs->sys_freq / 2))) | ||||
| +		spi->max_speed_hz = (rs->sys_freq / 2); | ||||
| + | ||||
| +	if (spi->max_speed_hz < (rs->sys_freq / 4097)) { | ||||
| +		dev_err(&spi->dev, "setup: requested speed is too low %d Hz\n", | ||||
| +			spi->max_speed_hz); | ||||
| +		return -EINVAL; | ||||
| +	} | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static const struct of_device_id mt7621_spi_match[] = { | ||||
| +	{ .compatible = "ralink,mt7621-spi" }, | ||||
| +	{}, | ||||
| +}; | ||||
| +MODULE_DEVICE_TABLE(of, mt7621_spi_match); | ||||
| + | ||||
| +static int mt7621_spi_probe(struct platform_device *pdev) | ||||
| +{ | ||||
| +	const struct of_device_id *match; | ||||
| +	struct spi_master *master; | ||||
| +	struct mt7621_spi *rs; | ||||
| +	unsigned long flags; | ||||
| +	void __iomem *base; | ||||
| +	struct resource *r; | ||||
| +	int status = 0; | ||||
| +	struct clk *clk; | ||||
| +	struct mt7621_spi_ops *ops; | ||||
| + | ||||
| +	match = of_match_device(mt7621_spi_match, &pdev->dev); | ||||
| +	if (!match) | ||||
| +		return -EINVAL; | ||||
| +	ops = (struct mt7621_spi_ops *)match->data; | ||||
| + | ||||
| +	r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||||
| +	base = devm_ioremap_resource(&pdev->dev, r); | ||||
| +	if (IS_ERR(base)) | ||||
| +		return PTR_ERR(base); | ||||
| + | ||||
| +	clk = devm_clk_get(&pdev->dev, NULL); | ||||
| +	if (IS_ERR(clk)) { | ||||
| +		dev_err(&pdev->dev, "unable to get SYS clock, err=%d\n", | ||||
| +			status); | ||||
| +		return PTR_ERR(clk); | ||||
| +	} | ||||
| + | ||||
| +	status = clk_prepare_enable(clk); | ||||
| +	if (status) | ||||
| +		return status; | ||||
| + | ||||
| +	master = spi_alloc_master(&pdev->dev, sizeof(*rs)); | ||||
| +	if (master == NULL) { | ||||
| +		dev_info(&pdev->dev, "master allocation failed\n"); | ||||
| +		return -ENOMEM; | ||||
| +	} | ||||
| + | ||||
| +	master->mode_bits = RT2880_SPI_MODE_BITS; | ||||
| + | ||||
| +	master->setup = mt7621_spi_setup; | ||||
| +	master->transfer_one_message = mt7621_spi_transfer_one_message; | ||||
| +	master->bits_per_word_mask = SPI_BPW_MASK(8); | ||||
| +	master->dev.of_node = pdev->dev.of_node; | ||||
| +	master->num_chipselect = 2; | ||||
| + | ||||
| +	dev_set_drvdata(&pdev->dev, master); | ||||
| + | ||||
| +	rs = spi_master_get_devdata(master); | ||||
| +	rs->base = base; | ||||
| +	rs->clk = clk; | ||||
| +	rs->master = master; | ||||
| +	rs->sys_freq = clk_get_rate(rs->clk); | ||||
| +	rs->ops = ops; | ||||
| +	dev_info(&pdev->dev, "sys_freq: %u\n", rs->sys_freq); | ||||
| +	spin_lock_irqsave(&rs->lock, flags); | ||||
| + | ||||
| +	device_reset(&pdev->dev); | ||||
| + | ||||
| +	mt7621_spi_reset(rs, 0); | ||||
| + | ||||
| +	return spi_register_master(master); | ||||
| +} | ||||
| + | ||||
| +static int mt7621_spi_remove(struct platform_device *pdev) | ||||
| +{ | ||||
| +	struct spi_master *master; | ||||
| +	struct mt7621_spi *rs; | ||||
| + | ||||
| +	master = dev_get_drvdata(&pdev->dev); | ||||
| +	rs = spi_master_get_devdata(master); | ||||
| + | ||||
| +	clk_disable(rs->clk); | ||||
| +	spi_unregister_master(master); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +MODULE_ALIAS("platform:" DRIVER_NAME); | ||||
| + | ||||
| +static struct platform_driver mt7621_spi_driver = { | ||||
| +	.driver = { | ||||
| +		.name = DRIVER_NAME, | ||||
| +		.owner = THIS_MODULE, | ||||
| +		.of_match_table = mt7621_spi_match, | ||||
| +	}, | ||||
| +	.probe = mt7621_spi_probe, | ||||
| +	.remove = mt7621_spi_remove, | ||||
| +}; | ||||
| + | ||||
| +module_platform_driver(mt7621_spi_driver); | ||||
| + | ||||
| +MODULE_DESCRIPTION("MT7621 SPI driver"); | ||||
| +MODULE_AUTHOR("Felix Fietkau <nbd@nbd.name>"); | ||||
| +MODULE_LICENSE("GPL"); | ||||
| @@ -0,0 +1,507 @@ | ||||
| From 723b8beaabf3c3c4b1ce69480141f1e926f3f3b2 Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <blogic@openwrt.org> | ||||
| Date: Sun, 27 Jul 2014 09:52:56 +0100 | ||||
| Subject: [PATCH 44/53] i2c: MIPS: adds ralink I2C driver | ||||
|  | ||||
| Signed-off-by: John Crispin <blogic@openwrt.org> | ||||
| --- | ||||
|  .../devicetree/bindings/i2c/i2c-ralink.txt         |   27 ++ | ||||
|  drivers/i2c/busses/Kconfig                         |    4 + | ||||
|  drivers/i2c/busses/Makefile                        |    1 + | ||||
|  drivers/i2c/busses/i2c-ralink.c                    |  327 ++++++++++++++++++++ | ||||
|  4 files changed, 359 insertions(+) | ||||
|  create mode 100644 Documentation/devicetree/bindings/i2c/i2c-ralink.txt | ||||
|  create mode 100644 drivers/i2c/busses/i2c-ralink.c | ||||
|  | ||||
| --- /dev/null | ||||
| +++ b/Documentation/devicetree/bindings/i2c/i2c-ralink.txt | ||||
| @@ -0,0 +1,27 @@ | ||||
| +I2C for Ralink platforms | ||||
| + | ||||
| +Required properties : | ||||
| +- compatible : Must be "link,rt3052-i2c" | ||||
| +- reg: physical base address of the controller and length of memory mapped | ||||
| +     region. | ||||
| +- #address-cells = <1>; | ||||
| +- #size-cells = <0>; | ||||
| + | ||||
| +Optional properties: | ||||
| +- Child nodes conforming to i2c bus binding | ||||
| + | ||||
| +Example : | ||||
| + | ||||
| +palmbus@10000000 { | ||||
| +	i2c@900 { | ||||
| +		compatible = "link,rt3052-i2c"; | ||||
| +		reg = <0x900 0x100>; | ||||
| +		#address-cells = <1>; | ||||
| +		#size-cells = <0>; | ||||
| + | ||||
| +		hwmon@4b { | ||||
| +			compatible = "national,lm92"; | ||||
| +			reg = <0x4b>; | ||||
| +		}; | ||||
| +	}; | ||||
| +}; | ||||
| --- a/drivers/i2c/busses/Kconfig | ||||
| +++ b/drivers/i2c/busses/Kconfig | ||||
| @@ -810,6 +810,11 @@ config I2C_RK3X | ||||
|  	  This driver can also be built as a module. If so, the module will | ||||
|  	  be called i2c-rk3x. | ||||
|   | ||||
| +config I2C_RALINK | ||||
| +	tristate "Ralink I2C Controller" | ||||
| +	depends on RALINK && !SOC_MT7621 | ||||
| +	select OF_I2C | ||||
| + | ||||
|  config HAVE_S3C2410_I2C | ||||
|  	bool | ||||
|  	help | ||||
| --- a/drivers/i2c/busses/Makefile | ||||
| +++ b/drivers/i2c/busses/Makefile | ||||
| @@ -75,6 +75,7 @@ obj-$(CONFIG_I2C_PNX)		+= i2c-pnx.o | ||||
|  obj-$(CONFIG_I2C_PUV3)		+= i2c-puv3.o | ||||
|  obj-$(CONFIG_I2C_PXA)		+= i2c-pxa.o | ||||
|  obj-$(CONFIG_I2C_PXA_PCI)	+= i2c-pxa-pci.o | ||||
| +obj-$(CONFIG_I2C_RALINK)	+= i2c-ralink.o | ||||
|  obj-$(CONFIG_I2C_QUP)		+= i2c-qup.o | ||||
|  obj-$(CONFIG_I2C_RIIC)		+= i2c-riic.o | ||||
|  obj-$(CONFIG_I2C_RK3X)		+= i2c-rk3x.o | ||||
| --- /dev/null | ||||
| +++ b/drivers/i2c/busses/i2c-ralink.c | ||||
| @@ -0,0 +1,435 @@ | ||||
| +/* | ||||
| + * drivers/i2c/busses/i2c-ralink.c | ||||
| + * | ||||
| + * Copyright (C) 2013 Steven Liu <steven_liu@mediatek.com> | ||||
| + * Copyright (C) 2016 Michael Lee <igvtee@gmail.com> | ||||
| + * | ||||
| + * Improve driver for i2cdetect from i2c-tools to detect i2c devices on the bus. | ||||
| + * (C) 2014 Sittisak <sittisaks@hotmail.com> | ||||
| + * | ||||
| + * 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 <linux/interrupt.h> | ||||
| +#include <linux/kernel.h> | ||||
| +#include <linux/module.h> | ||||
| +#include <linux/reset.h> | ||||
| +#include <linux/delay.h> | ||||
| +#include <linux/slab.h> | ||||
| +#include <linux/init.h> | ||||
| +#include <linux/errno.h> | ||||
| +#include <linux/platform_device.h> | ||||
| +#include <linux/of_platform.h> | ||||
| +#include <linux/i2c.h> | ||||
| +#include <linux/io.h> | ||||
| +#include <linux/err.h> | ||||
| +#include <linux/clk.h> | ||||
| + | ||||
| +#define REG_CONFIG_REG		0x00 | ||||
| +#define REG_CLKDIV_REG		0x04 | ||||
| +#define REG_DEVADDR_REG		0x08 | ||||
| +#define REG_ADDR_REG		0x0C | ||||
| +#define REG_DATAOUT_REG		0x10 | ||||
| +#define REG_DATAIN_REG		0x14 | ||||
| +#define REG_STATUS_REG		0x18 | ||||
| +#define REG_STARTXFR_REG	0x1C | ||||
| +#define REG_BYTECNT_REG		0x20 | ||||
| + | ||||
| +/* REG_CONFIG_REG */ | ||||
| +#define I2C_ADDRLEN_OFFSET	5 | ||||
| +#define I2C_DEVADLEN_OFFSET	2 | ||||
| +#define I2C_ADDRLEN_MASK	0x3 | ||||
| +#define I2C_ADDR_DIS		BIT(1) | ||||
| +#define I2C_DEVADDR_DIS		BIT(0) | ||||
| +#define I2C_ADDRLEN_8		(7 << I2C_ADDRLEN_OFFSET) | ||||
| +#define I2C_DEVADLEN_7		(6 << I2C_DEVADLEN_OFFSET) | ||||
| +#define I2C_CONF_DEFAULT	(I2C_ADDRLEN_8 | I2C_DEVADLEN_7) | ||||
| + | ||||
| +/* REG_CLKDIV_REG */ | ||||
| +#define I2C_CLKDIV_MASK		0xffff | ||||
| + | ||||
| +/* REG_DEVADDR_REG */ | ||||
| +#define I2C_DEVADDR_MASK	0x7f | ||||
| + | ||||
| +/* REG_ADDR_REG */ | ||||
| +#define I2C_ADDR_MASK		0xff | ||||
| + | ||||
| +/* REG_STATUS_REG */ | ||||
| +#define I2C_STARTERR		BIT(4) | ||||
| +#define I2C_ACKERR		BIT(3) | ||||
| +#define I2C_DATARDY		BIT(2) | ||||
| +#define I2C_SDOEMPTY		BIT(1) | ||||
| +#define I2C_BUSY		BIT(0) | ||||
| + | ||||
| +/* REG_STARTXFR_REG */ | ||||
| +#define NOSTOP_CMD		BIT(2) | ||||
| +#define NODATA_CMD		BIT(1) | ||||
| +#define READ_CMD		BIT(0) | ||||
| + | ||||
| +/* REG_BYTECNT_REG */ | ||||
| +#define BYTECNT_MAX		64 | ||||
| +#define SET_BYTECNT(x)		(x - 1) | ||||
| + | ||||
| +/* timeout waiting for I2C devices to respond (clock streching) */ | ||||
| +#define TIMEOUT_MS              1000 | ||||
| +#define DELAY_INTERVAL_US       100 | ||||
| + | ||||
| +struct rt_i2c { | ||||
| +	void __iomem *base; | ||||
| +	struct clk *clk; | ||||
| +	struct device *dev; | ||||
| +	struct i2c_adapter adap; | ||||
| +	u32 cur_clk; | ||||
| +	u32 clk_div; | ||||
| +	u32 flags; | ||||
| +}; | ||||
| + | ||||
| +static void rt_i2c_w32(struct rt_i2c *i2c, u32 val, unsigned reg) | ||||
| +{ | ||||
| +	iowrite32(val, i2c->base + reg); | ||||
| +} | ||||
| + | ||||
| +static u32 rt_i2c_r32(struct rt_i2c *i2c, unsigned reg) | ||||
| +{ | ||||
| +	return ioread32(i2c->base + reg); | ||||
| +} | ||||
| + | ||||
| +static int poll_down_timeout(void __iomem *addr, u32 mask) | ||||
| +{ | ||||
| +	unsigned long timeout = jiffies + msecs_to_jiffies(TIMEOUT_MS); | ||||
| + | ||||
| +	do { | ||||
| +		if (!(readl_relaxed(addr) & mask)) | ||||
| +			return 0; | ||||
| + | ||||
| +		usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50); | ||||
| +	} while (time_before(jiffies, timeout)); | ||||
| + | ||||
| +	return (readl_relaxed(addr) & mask) ? -EAGAIN : 0; | ||||
| +} | ||||
| + | ||||
| +static int rt_i2c_wait_idle(struct rt_i2c *i2c) | ||||
| +{ | ||||
| +	int ret; | ||||
| + | ||||
| +	ret = poll_down_timeout(i2c->base + REG_STATUS_REG, I2C_BUSY); | ||||
| +	if (ret < 0) | ||||
| +		dev_dbg(i2c->dev, "idle err(%d)\n", ret); | ||||
| + | ||||
| +	return ret; | ||||
| +} | ||||
| + | ||||
| +static int poll_up_timeout(void __iomem *addr, u32 mask) | ||||
| +{ | ||||
| +	unsigned long timeout = jiffies + msecs_to_jiffies(TIMEOUT_MS); | ||||
| +	u32 status; | ||||
| + | ||||
| +	do { | ||||
| +		status = readl_relaxed(addr); | ||||
| + | ||||
| +		/* check error status */ | ||||
| +		if (status & I2C_STARTERR) | ||||
| +			return -EAGAIN; | ||||
| +		else if (status & I2C_ACKERR) | ||||
| +			return -ENXIO; | ||||
| +		else if (status & mask) | ||||
| +			return 0; | ||||
| + | ||||
| +		usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50); | ||||
| +	} while (time_before(jiffies, timeout)); | ||||
| + | ||||
| +	return -ETIMEDOUT; | ||||
| +} | ||||
| + | ||||
| +static int rt_i2c_wait_rx_done(struct rt_i2c *i2c) | ||||
| +{ | ||||
| +	int ret; | ||||
| + | ||||
| +	ret = poll_up_timeout(i2c->base + REG_STATUS_REG, I2C_DATARDY); | ||||
| +	if (ret < 0) | ||||
| +		dev_dbg(i2c->dev, "rx err(%d)\n", ret); | ||||
| + | ||||
| +	return ret; | ||||
| +} | ||||
| + | ||||
| +static int rt_i2c_wait_tx_done(struct rt_i2c *i2c) | ||||
| +{ | ||||
| +	int ret; | ||||
| + | ||||
| +	ret = poll_up_timeout(i2c->base + REG_STATUS_REG, I2C_SDOEMPTY); | ||||
| +	if (ret < 0) | ||||
| +		dev_dbg(i2c->dev, "tx err(%d)\n", ret); | ||||
| + | ||||
| +	return ret; | ||||
| +} | ||||
| + | ||||
| +static void rt_i2c_reset(struct rt_i2c *i2c) | ||||
| +{ | ||||
| +	device_reset(i2c->adap.dev.parent); | ||||
| +	barrier(); | ||||
| +	rt_i2c_w32(i2c, i2c->clk_div, REG_CLKDIV_REG); | ||||
| +} | ||||
| + | ||||
| +static void rt_i2c_dump_reg(struct rt_i2c *i2c) | ||||
| +{ | ||||
| +	dev_dbg(i2c->dev, "conf %08x, clkdiv %08x, devaddr %08x, " \ | ||||
| +			"addr %08x, dataout %08x, datain %08x, " \ | ||||
| +			"status %08x, startxfr %08x, bytecnt %08x\n", | ||||
| +			rt_i2c_r32(i2c, REG_CONFIG_REG), | ||||
| +			rt_i2c_r32(i2c, REG_CLKDIV_REG), | ||||
| +			rt_i2c_r32(i2c, REG_DEVADDR_REG), | ||||
| +			rt_i2c_r32(i2c, REG_ADDR_REG), | ||||
| +			rt_i2c_r32(i2c, REG_DATAOUT_REG), | ||||
| +			rt_i2c_r32(i2c, REG_DATAIN_REG), | ||||
| +			rt_i2c_r32(i2c, REG_STATUS_REG), | ||||
| +			rt_i2c_r32(i2c, REG_STARTXFR_REG), | ||||
| +			rt_i2c_r32(i2c, REG_BYTECNT_REG)); | ||||
| +} | ||||
| + | ||||
| +static int rt_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, | ||||
| +		int num) | ||||
| +{ | ||||
| +	struct rt_i2c *i2c; | ||||
| +	struct i2c_msg *pmsg; | ||||
| +	unsigned char addr; | ||||
| +	int i, j, ret; | ||||
| +	u32 cmd; | ||||
| + | ||||
| +	i2c = i2c_get_adapdata(adap); | ||||
| + | ||||
| +	for (i = 0; i < num; i++) { | ||||
| +		pmsg = &msgs[i]; | ||||
| +		if (i == (num - 1)) | ||||
| +			cmd = 0; | ||||
| +		else | ||||
| +			cmd = NOSTOP_CMD; | ||||
| + | ||||
| +		dev_dbg(i2c->dev, "addr: 0x%x, len: %d, flags: 0x%x, stop: %d\n", | ||||
| +				pmsg->addr, pmsg->len, pmsg->flags, | ||||
| +				(cmd == 0)? 1 : 0); | ||||
| + | ||||
| +		/* wait hardware idle */ | ||||
| +		if ((ret = rt_i2c_wait_idle(i2c))) | ||||
| +			goto err_timeout; | ||||
| + | ||||
| +		if (pmsg->flags & I2C_M_TEN) { | ||||
| +			rt_i2c_w32(i2c, I2C_CONF_DEFAULT, REG_CONFIG_REG); | ||||
| +			/* 10 bits address */ | ||||
| +			addr = 0x78 | ((pmsg->addr >> 8) & 0x03); | ||||
| +			rt_i2c_w32(i2c, addr & I2C_DEVADDR_MASK, | ||||
| +					REG_DEVADDR_REG); | ||||
| +			rt_i2c_w32(i2c, pmsg->addr & I2C_ADDR_MASK, | ||||
| +					REG_ADDR_REG); | ||||
| +		} else { | ||||
| +			rt_i2c_w32(i2c, I2C_CONF_DEFAULT | I2C_ADDR_DIS, | ||||
| +					REG_CONFIG_REG); | ||||
| +			/* 7 bits address */ | ||||
| +			rt_i2c_w32(i2c, pmsg->addr & I2C_DEVADDR_MASK, | ||||
| +					REG_DEVADDR_REG); | ||||
| +		} | ||||
| + | ||||
| +		/* buffer length */ | ||||
| +		if (pmsg->len == 0) | ||||
| +			cmd |= NODATA_CMD; | ||||
| +		else | ||||
| +			rt_i2c_w32(i2c, SET_BYTECNT(pmsg->len), | ||||
| +					REG_BYTECNT_REG); | ||||
| + | ||||
| +		j = 0; | ||||
| +		if (pmsg->flags & I2C_M_RD) { | ||||
| +			cmd |= READ_CMD; | ||||
| +			/* start transfer */ | ||||
| +			barrier(); | ||||
| +			rt_i2c_w32(i2c, cmd, REG_STARTXFR_REG); | ||||
| +			do { | ||||
| +				/* wait */ | ||||
| +				if ((ret = rt_i2c_wait_rx_done(i2c))) | ||||
| +					goto err_timeout; | ||||
| +				/* read data */ | ||||
| +				if (pmsg->len) | ||||
| +					pmsg->buf[j] = rt_i2c_r32(i2c, | ||||
| +							REG_DATAIN_REG); | ||||
| +				j++; | ||||
| +			} while (j < pmsg->len); | ||||
| +		} else { | ||||
| +			do { | ||||
| +				/* write data */ | ||||
| +				if (pmsg->len) | ||||
| +					rt_i2c_w32(i2c, pmsg->buf[j], | ||||
| +							REG_DATAOUT_REG); | ||||
| +				/* start transfer */ | ||||
| +				if (j == 0) { | ||||
| +					barrier(); | ||||
| +					rt_i2c_w32(i2c, cmd, REG_STARTXFR_REG); | ||||
| +				} | ||||
| +				/* wait */ | ||||
| +				if ((ret = rt_i2c_wait_tx_done(i2c))) | ||||
| +					goto err_timeout; | ||||
| +				j++; | ||||
| +			} while (j < pmsg->len); | ||||
| +		} | ||||
| +	} | ||||
| +	/* the return value is number of executed messages */ | ||||
| +	ret = i; | ||||
| + | ||||
| +	return ret; | ||||
| + | ||||
| +err_timeout: | ||||
| +	rt_i2c_dump_reg(i2c); | ||||
| +	rt_i2c_reset(i2c); | ||||
| +	return ret; | ||||
| +} | ||||
| + | ||||
| +static u32 rt_i2c_func(struct i2c_adapter *a) | ||||
| +{ | ||||
| +	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; | ||||
| +} | ||||
| + | ||||
| +static const struct i2c_algorithm rt_i2c_algo = { | ||||
| +	.master_xfer	= rt_i2c_master_xfer, | ||||
| +	.functionality	= rt_i2c_func, | ||||
| +}; | ||||
| + | ||||
| +static const struct of_device_id i2c_rt_dt_ids[] = { | ||||
| +	{ .compatible = "ralink,rt2880-i2c" }, | ||||
| +	{ /* sentinel */ } | ||||
| +}; | ||||
| + | ||||
| +MODULE_DEVICE_TABLE(of, i2c_rt_dt_ids); | ||||
| + | ||||
| +static struct i2c_adapter_quirks rt_i2c_quirks = { | ||||
| +        .max_write_len = BYTECNT_MAX, | ||||
| +        .max_read_len = BYTECNT_MAX, | ||||
| +}; | ||||
| + | ||||
| +static int rt_i2c_init(struct rt_i2c *i2c) | ||||
| +{ | ||||
| +	u32 reg; | ||||
| + | ||||
| +	/* i2c_sclk = periph_clk / ((2 * clk_div) + 5) */ | ||||
| +	i2c->clk_div = (clk_get_rate(i2c->clk) - (5 * i2c->cur_clk)) / | ||||
| +		(2 * i2c->cur_clk); | ||||
| +	if (i2c->clk_div < 8) | ||||
| +		i2c->clk_div = 8; | ||||
| +	if (i2c->clk_div > I2C_CLKDIV_MASK) | ||||
| +		i2c->clk_div = I2C_CLKDIV_MASK; | ||||
| + | ||||
| +	/* check support combinde/repeated start message */ | ||||
| +	rt_i2c_w32(i2c, NOSTOP_CMD, REG_STARTXFR_REG); | ||||
| +	reg = rt_i2c_r32(i2c, REG_STARTXFR_REG) & NOSTOP_CMD; | ||||
| + | ||||
| +	rt_i2c_reset(i2c); | ||||
| + | ||||
| +	return reg; | ||||
| +} | ||||
| + | ||||
| +static int rt_i2c_probe(struct platform_device *pdev) | ||||
| +{ | ||||
| +	struct resource *res; | ||||
| +	struct rt_i2c *i2c; | ||||
| +	struct i2c_adapter *adap; | ||||
| +	const struct of_device_id *match; | ||||
| +	int ret, restart; | ||||
| + | ||||
| +	match = of_match_device(i2c_rt_dt_ids, &pdev->dev); | ||||
| + | ||||
| +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||||
| +	if (!res) { | ||||
| +		dev_err(&pdev->dev, "no memory resource found\n"); | ||||
| +		return -ENODEV; | ||||
| +	} | ||||
| + | ||||
| +	i2c = devm_kzalloc(&pdev->dev, sizeof(struct rt_i2c), GFP_KERNEL); | ||||
| +	if (!i2c) { | ||||
| +		dev_err(&pdev->dev, "failed to allocate i2c_adapter\n"); | ||||
| +		return -ENOMEM; | ||||
| +	} | ||||
| + | ||||
| +	i2c->base = devm_ioremap_resource(&pdev->dev, res); | ||||
| +	if (IS_ERR(i2c->base)) | ||||
| +		return PTR_ERR(i2c->base); | ||||
| + | ||||
| +	i2c->clk = devm_clk_get(&pdev->dev, NULL); | ||||
| +	if (IS_ERR(i2c->clk)) { | ||||
| +		dev_err(&pdev->dev, "no clock defined\n"); | ||||
| +		return -ENODEV; | ||||
| +	} | ||||
| +	clk_prepare_enable(i2c->clk); | ||||
| +	i2c->dev = &pdev->dev; | ||||
| + | ||||
| +	if (of_property_read_u32(pdev->dev.of_node, | ||||
| +				"clock-frequency", &i2c->cur_clk)) | ||||
| +		i2c->cur_clk = 100000; | ||||
| + | ||||
| +	adap = &i2c->adap; | ||||
| +	adap->owner = THIS_MODULE; | ||||
| +	adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; | ||||
| +	adap->algo = &rt_i2c_algo; | ||||
| +	adap->retries = 3; | ||||
| +	adap->dev.parent = &pdev->dev; | ||||
| +	i2c_set_adapdata(adap, i2c); | ||||
| +	adap->dev.of_node = pdev->dev.of_node; | ||||
| +	strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name)); | ||||
| +	adap->quirks = &rt_i2c_quirks; | ||||
| + | ||||
| +	platform_set_drvdata(pdev, i2c); | ||||
| + | ||||
| +	restart = rt_i2c_init(i2c); | ||||
| + | ||||
| +	ret = i2c_add_adapter(adap); | ||||
| +	if (ret < 0) { | ||||
| +		dev_err(&pdev->dev, "failed to add adapter\n"); | ||||
| +		clk_disable_unprepare(i2c->clk); | ||||
| +		return ret; | ||||
| +	} | ||||
| + | ||||
| +	dev_info(&pdev->dev, "clock %uKHz, re-start %ssupport\n", | ||||
| +			i2c->cur_clk/1000, restart ? "" : "not "); | ||||
| + | ||||
| +	return ret; | ||||
| +} | ||||
| + | ||||
| +static int rt_i2c_remove(struct platform_device *pdev) | ||||
| +{ | ||||
| +	struct rt_i2c *i2c = platform_get_drvdata(pdev); | ||||
| + | ||||
| +	i2c_del_adapter(&i2c->adap); | ||||
| +	clk_disable_unprepare(i2c->clk); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static struct platform_driver rt_i2c_driver = { | ||||
| +	.probe		= rt_i2c_probe, | ||||
| +	.remove		= rt_i2c_remove, | ||||
| +	.driver		= { | ||||
| +		.owner	= THIS_MODULE, | ||||
| +		.name	= "i2c-ralink", | ||||
| +		.of_match_table = i2c_rt_dt_ids, | ||||
| +	}, | ||||
| +}; | ||||
| + | ||||
| +static int __init i2c_rt_init (void) | ||||
| +{ | ||||
| +	return platform_driver_register(&rt_i2c_driver); | ||||
| +} | ||||
| +subsys_initcall(i2c_rt_init); | ||||
| + | ||||
| +static void __exit i2c_rt_exit (void) | ||||
| +{ | ||||
| +	platform_driver_unregister(&rt_i2c_driver); | ||||
| +} | ||||
| +module_exit(i2c_rt_exit); | ||||
| + | ||||
| +MODULE_AUTHOR("Steven Liu <steven_liu@mediatek.com>"); | ||||
| +MODULE_DESCRIPTION("Ralink I2c host driver"); | ||||
| +MODULE_LICENSE("GPL"); | ||||
| +MODULE_ALIAS("platform:Ralink-I2C"); | ||||
							
								
								
									
										473
									
								
								target/linux/ramips/patches-4.9/0045-i2c-add-mt7621-driver.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										473
									
								
								target/linux/ramips/patches-4.9/0045-i2c-add-mt7621-driver.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,473 @@ | ||||
| From d5c54ff3d1db0a4348fa04d8e78f3bf6063e3afc Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <blogic@openwrt.org> | ||||
| Date: Mon, 7 Dec 2015 17:21:27 +0100 | ||||
| Subject: [PATCH 45/53] i2c: add mt7621 driver | ||||
|  | ||||
| Signed-off-by: John Crispin <blogic@openwrt.org> | ||||
| --- | ||||
|  drivers/i2c/busses/Kconfig      |    4 + | ||||
|  drivers/i2c/busses/Makefile     |    1 + | ||||
|  drivers/i2c/busses/i2c-mt7621.c |  303 +++++++++++++++++++++++++++++++++++++++ | ||||
|  3 files changed, 308 insertions(+) | ||||
|  create mode 100644 drivers/i2c/busses/i2c-mt7621.c | ||||
|  | ||||
| --- a/drivers/i2c/busses/Kconfig | ||||
| +++ b/drivers/i2c/busses/Kconfig | ||||
| @@ -815,6 +815,11 @@ config I2C_RALINK | ||||
|  	depends on RALINK && !SOC_MT7621 | ||||
|  	select OF_I2C | ||||
|   | ||||
| +config I2C_MT7621 | ||||
| +	tristate "MT7621/MT7628 I2C Controller" | ||||
| +	depends on RALINK && (SOC_MT7620 || SOC_MT7621) | ||||
| +	select OF_I2C | ||||
| + | ||||
|  config HAVE_S3C2410_I2C | ||||
|  	bool | ||||
|  	help | ||||
| --- a/drivers/i2c/busses/Makefile | ||||
| +++ b/drivers/i2c/busses/Makefile | ||||
| @@ -76,6 +76,7 @@ obj-$(CONFIG_I2C_PUV3)		+= i2c-puv3.o | ||||
|  obj-$(CONFIG_I2C_PXA)		+= i2c-pxa.o | ||||
|  obj-$(CONFIG_I2C_PXA_PCI)	+= i2c-pxa-pci.o | ||||
|  obj-$(CONFIG_I2C_RALINK)	+= i2c-ralink.o | ||||
| +obj-$(CONFIG_I2C_MT7621)	+= i2c-mt7621.o | ||||
|  obj-$(CONFIG_I2C_QUP)		+= i2c-qup.o | ||||
|  obj-$(CONFIG_I2C_RIIC)		+= i2c-riic.o | ||||
|  obj-$(CONFIG_I2C_RK3X)		+= i2c-rk3x.o | ||||
| --- /dev/null | ||||
| +++ b/drivers/i2c/busses/i2c-mt7621.c | ||||
| @@ -0,0 +1,433 @@ | ||||
| +/* | ||||
| + * drivers/i2c/busses/i2c-mt7621.c | ||||
| + * | ||||
| + * Copyright (C) 2013 Steven Liu <steven_liu@mediatek.com> | ||||
| + * Copyright (C) 2016 Michael Lee <igvtee@gmail.com> | ||||
| + * | ||||
| + * Improve driver for i2cdetect from i2c-tools to detect i2c devices on the bus. | ||||
| + * (C) 2014 Sittisak <sittisaks@hotmail.com> | ||||
| + * | ||||
| + * 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 <linux/interrupt.h> | ||||
| +#include <linux/kernel.h> | ||||
| +#include <linux/module.h> | ||||
| +#include <linux/reset.h> | ||||
| +#include <linux/delay.h> | ||||
| +#include <linux/slab.h> | ||||
| +#include <linux/init.h> | ||||
| +#include <linux/errno.h> | ||||
| +#include <linux/platform_device.h> | ||||
| +#include <linux/of_platform.h> | ||||
| +#include <linux/i2c.h> | ||||
| +#include <linux/io.h> | ||||
| +#include <linux/err.h> | ||||
| +#include <linux/clk.h> | ||||
| + | ||||
| +#define REG_SM0CFG0		0x08 | ||||
| +#define REG_SM0DOUT		0x10 | ||||
| +#define REG_SM0DIN		0x14 | ||||
| +#define REG_SM0ST		0x18 | ||||
| +#define REG_SM0AUTO		0x1C | ||||
| +#define REG_SM0CFG1		0x20 | ||||
| +#define REG_SM0CFG2		0x28 | ||||
| +#define REG_SM0CTL0		0x40 | ||||
| +#define REG_SM0CTL1		0x44 | ||||
| +#define REG_SM0D0		0x50 | ||||
| +#define REG_SM0D1		0x54 | ||||
| +#define REG_PINTEN		0x5C | ||||
| +#define REG_PINTST		0x60 | ||||
| +#define REG_PINTCL		0x64 | ||||
| + | ||||
| +/* REG_SM0CFG0 */ | ||||
| +#define I2C_DEVADDR_MASK	0x7f | ||||
| + | ||||
| +/* REG_SM0ST */ | ||||
| +#define I2C_DATARDY		BIT(2) | ||||
| +#define I2C_SDOEMPTY		BIT(1) | ||||
| +#define I2C_BUSY		BIT(0) | ||||
| + | ||||
| +/* REG_SM0AUTO */ | ||||
| +#define READ_CMD		BIT(0) | ||||
| + | ||||
| +/* REG_SM0CFG1 */ | ||||
| +#define BYTECNT_MAX		64 | ||||
| +#define SET_BYTECNT(x)		(x - 1) | ||||
| + | ||||
| +/* REG_SM0CFG2 */ | ||||
| +#define AUTOMODE_EN		BIT(0) | ||||
| + | ||||
| +/* REG_SM0CTL0 */ | ||||
| +#define ODRAIN_HIGH_SM0		BIT(31) | ||||
| +#define VSYNC_SHIFT		28 | ||||
| +#define VSYNC_MASK		0x3 | ||||
| +#define VSYNC_PULSE		(0x1 << VSYNC_SHIFT) | ||||
| +#define VSYNC_RISING		(0x2 << VSYNC_SHIFT) | ||||
| +#define CLK_DIV_SHIFT		16 | ||||
| +#define CLK_DIV_MASK		0xfff | ||||
| +#define DEG_CNT_SHIFT		8 | ||||
| +#define DEG_CNT_MASK		0xff | ||||
| +#define WAIT_HIGH		BIT(6) | ||||
| +#define DEG_EN			BIT(5) | ||||
| +#define CS_STATUA		BIT(4) | ||||
| +#define SCL_STATUS		BIT(3) | ||||
| +#define SDA_STATUS		BIT(2) | ||||
| +#define SM0_EN			BIT(1) | ||||
| +#define SCL_STRECH		BIT(0) | ||||
| + | ||||
| +/* REG_SM0CTL1 */ | ||||
| +#define ACK_SHIFT		16 | ||||
| +#define ACK_MASK		0xff | ||||
| +#define PGLEN_SHIFT		8 | ||||
| +#define PGLEN_MASK		0x7 | ||||
| +#define SM0_MODE_SHIFT		4 | ||||
| +#define SM0_MODE_MASK		0x7 | ||||
| +#define SM0_MODE_START		0x1 | ||||
| +#define SM0_MODE_WRITE		0x2 | ||||
| +#define SM0_MODE_STOP		0x3 | ||||
| +#define SM0_MODE_READ_NACK	0x4 | ||||
| +#define SM0_MODE_READ_ACK	0x5 | ||||
| +#define SM0_TRI_BUSY		BIT(0) | ||||
| + | ||||
| +/* timeout waiting for I2C devices to respond (clock streching) */ | ||||
| +#define TIMEOUT_MS              1000 | ||||
| +#define DELAY_INTERVAL_US       100 | ||||
| + | ||||
| +struct mtk_i2c { | ||||
| +	void __iomem *base; | ||||
| +	struct clk *clk; | ||||
| +	struct device *dev; | ||||
| +	struct i2c_adapter adap; | ||||
| +	u32 cur_clk; | ||||
| +	u32 clk_div; | ||||
| +	u32 flags; | ||||
| +}; | ||||
| + | ||||
| +static void mtk_i2c_w32(struct mtk_i2c *i2c, u32 val, unsigned reg) | ||||
| +{ | ||||
| +	iowrite32(val, i2c->base + reg); | ||||
| +} | ||||
| + | ||||
| +static u32 mtk_i2c_r32(struct mtk_i2c *i2c, unsigned reg) | ||||
| +{ | ||||
| +	return ioread32(i2c->base + reg); | ||||
| +} | ||||
| + | ||||
| +static int poll_down_timeout(void __iomem *addr, u32 mask) | ||||
| +{ | ||||
| +	unsigned long timeout = jiffies + msecs_to_jiffies(TIMEOUT_MS); | ||||
| + | ||||
| +	do { | ||||
| +		if (!(readl_relaxed(addr) & mask)) | ||||
| +			return 0; | ||||
| + | ||||
| +		usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50); | ||||
| +	} while (time_before(jiffies, timeout)); | ||||
| + | ||||
| +	return (readl_relaxed(addr) & mask) ? -EAGAIN : 0; | ||||
| +} | ||||
| + | ||||
| +static int mtk_i2c_wait_idle(struct mtk_i2c *i2c) | ||||
| +{ | ||||
| +	int ret; | ||||
| + | ||||
| +	ret = poll_down_timeout(i2c->base + REG_SM0ST, I2C_BUSY); | ||||
| +	if (ret < 0) | ||||
| +		dev_dbg(i2c->dev, "idle err(%d)\n", ret); | ||||
| + | ||||
| +	return ret; | ||||
| +} | ||||
| + | ||||
| +static int poll_up_timeout(void __iomem *addr, u32 mask) | ||||
| +{ | ||||
| +	unsigned long timeout = jiffies + msecs_to_jiffies(TIMEOUT_MS); | ||||
| +	u32 status; | ||||
| + | ||||
| +	do { | ||||
| +		status = readl_relaxed(addr); | ||||
| +		if (status & mask) | ||||
| +			return 0; | ||||
| +		usleep_range(DELAY_INTERVAL_US, DELAY_INTERVAL_US + 50); | ||||
| +	} while (time_before(jiffies, timeout)); | ||||
| + | ||||
| +	return -ETIMEDOUT; | ||||
| +} | ||||
| + | ||||
| +static int mtk_i2c_wait_rx_done(struct mtk_i2c *i2c) | ||||
| +{ | ||||
| +	int ret; | ||||
| + | ||||
| +	ret = poll_up_timeout(i2c->base + REG_SM0ST, I2C_DATARDY); | ||||
| +	if (ret < 0) | ||||
| +		dev_dbg(i2c->dev, "rx err(%d)\n", ret); | ||||
| + | ||||
| +	return ret; | ||||
| +} | ||||
| + | ||||
| +static int mtk_i2c_wait_tx_done(struct mtk_i2c *i2c) | ||||
| +{ | ||||
| +	int ret; | ||||
| + | ||||
| +	ret = poll_up_timeout(i2c->base + REG_SM0ST, I2C_SDOEMPTY); | ||||
| +	if (ret < 0) | ||||
| +		dev_dbg(i2c->dev, "tx err(%d)\n", ret); | ||||
| + | ||||
| +	return ret; | ||||
| +} | ||||
| + | ||||
| +static void mtk_i2c_reset(struct mtk_i2c *i2c) | ||||
| +{ | ||||
| +	u32 reg; | ||||
| +	device_reset(i2c->adap.dev.parent); | ||||
| +	barrier(); | ||||
| + | ||||
| +	/* ctrl0 */ | ||||
| +	reg = ODRAIN_HIGH_SM0 | VSYNC_PULSE | (i2c->clk_div << CLK_DIV_SHIFT) | | ||||
| +		WAIT_HIGH | SM0_EN; | ||||
| +	mtk_i2c_w32(i2c, reg, REG_SM0CTL0); | ||||
| + | ||||
| +	/* auto mode */ | ||||
| +	mtk_i2c_w32(i2c, AUTOMODE_EN, REG_SM0CFG2); | ||||
| +} | ||||
| + | ||||
| +static void mtk_i2c_dump_reg(struct mtk_i2c *i2c) | ||||
| +{ | ||||
| +	dev_dbg(i2c->dev, "cfg0 %08x, dout %08x, din %08x, " \ | ||||
| +			"status %08x, auto %08x, cfg1 %08x, " \ | ||||
| +			"cfg2 %08x, ctl0 %08x, ctl1 %08x\n", | ||||
| +			mtk_i2c_r32(i2c, REG_SM0CFG0), | ||||
| +			mtk_i2c_r32(i2c, REG_SM0DOUT), | ||||
| +			mtk_i2c_r32(i2c, REG_SM0DIN), | ||||
| +			mtk_i2c_r32(i2c, REG_SM0ST), | ||||
| +			mtk_i2c_r32(i2c, REG_SM0AUTO), | ||||
| +			mtk_i2c_r32(i2c, REG_SM0CFG1), | ||||
| +			mtk_i2c_r32(i2c, REG_SM0CFG2), | ||||
| +			mtk_i2c_r32(i2c, REG_SM0CTL0), | ||||
| +			mtk_i2c_r32(i2c, REG_SM0CTL1)); | ||||
| +} | ||||
| + | ||||
| +static int mtk_i2c_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, | ||||
| +		int num) | ||||
| +{ | ||||
| +	struct mtk_i2c *i2c; | ||||
| +	struct i2c_msg *pmsg; | ||||
| +	int i, j, ret; | ||||
| +	u32 cmd; | ||||
| + | ||||
| +	i2c = i2c_get_adapdata(adap); | ||||
| + | ||||
| +	for (i = 0; i < num; i++) { | ||||
| +		pmsg = &msgs[i]; | ||||
| +		cmd = 0; | ||||
| + | ||||
| +		dev_dbg(i2c->dev, "addr: 0x%x, len: %d, flags: 0x%x\n", | ||||
| +				pmsg->addr, pmsg->len, pmsg->flags); | ||||
| + | ||||
| +		/* wait hardware idle */ | ||||
| +		if ((ret = mtk_i2c_wait_idle(i2c))) | ||||
| +			goto err_timeout; | ||||
| + | ||||
| +		if (pmsg->flags & I2C_M_TEN) { | ||||
| +			dev_dbg(i2c->dev, "10 bits addr not supported\n"); | ||||
| +			return -EINVAL; | ||||
| +		} else { | ||||
| +			/* 7 bits address */ | ||||
| +			mtk_i2c_w32(i2c, pmsg->addr & I2C_DEVADDR_MASK, | ||||
| +					REG_SM0CFG0); | ||||
| +		} | ||||
| + | ||||
| +		/* buffer length */ | ||||
| +		if (pmsg->len == 0) { | ||||
| +			dev_dbg(i2c->dev, "length is 0\n"); | ||||
| +			return -EINVAL; | ||||
| +		} else | ||||
| +			mtk_i2c_w32(i2c, SET_BYTECNT(pmsg->len), | ||||
| +					REG_SM0CFG1); | ||||
| + | ||||
| +		j = 0; | ||||
| +		if (pmsg->flags & I2C_M_RD) { | ||||
| +			cmd |= READ_CMD; | ||||
| +			/* start transfer */ | ||||
| +			barrier(); | ||||
| +			mtk_i2c_w32(i2c, cmd, REG_SM0AUTO); | ||||
| +			do { | ||||
| +				/* wait */ | ||||
| +				if ((ret = mtk_i2c_wait_rx_done(i2c))) | ||||
| +					goto err_timeout; | ||||
| +				/* read data */ | ||||
| +				if (pmsg->len) | ||||
| +					pmsg->buf[j] = mtk_i2c_r32(i2c, | ||||
| +							REG_SM0DIN); | ||||
| +				j++; | ||||
| +			} while (j < pmsg->len); | ||||
| +		} else { | ||||
| +			do { | ||||
| +				/* write data */ | ||||
| +				if (pmsg->len) | ||||
| +					mtk_i2c_w32(i2c, pmsg->buf[j], | ||||
| +							REG_SM0DOUT); | ||||
| +				/* start transfer */ | ||||
| +				if (j == 0) { | ||||
| +					barrier(); | ||||
| +					mtk_i2c_w32(i2c, cmd, REG_SM0AUTO); | ||||
| +				} | ||||
| +				/* wait */ | ||||
| +				if ((ret = mtk_i2c_wait_tx_done(i2c))) | ||||
| +					goto err_timeout; | ||||
| +				j++; | ||||
| +			} while (j < pmsg->len); | ||||
| +		} | ||||
| +	} | ||||
| +	/* the return value is number of executed messages */ | ||||
| +	ret = i; | ||||
| + | ||||
| +	return ret; | ||||
| + | ||||
| +err_timeout: | ||||
| +	mtk_i2c_dump_reg(i2c); | ||||
| +	mtk_i2c_reset(i2c); | ||||
| +	return ret; | ||||
| +} | ||||
| + | ||||
| +static u32 mtk_i2c_func(struct i2c_adapter *a) | ||||
| +{ | ||||
| +	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; | ||||
| +} | ||||
| + | ||||
| +static const struct i2c_algorithm mtk_i2c_algo = { | ||||
| +	.master_xfer	= mtk_i2c_master_xfer, | ||||
| +	.functionality	= mtk_i2c_func, | ||||
| +}; | ||||
| + | ||||
| +static const struct of_device_id i2c_mtk_dt_ids[] = { | ||||
| +	{ .compatible = "mediatek,mt7621-i2c" }, | ||||
| +	{ /* sentinel */ } | ||||
| +}; | ||||
| + | ||||
| +MODULE_DEVICE_TABLE(of, i2c_mtk_dt_ids); | ||||
| + | ||||
| +static struct i2c_adapter_quirks mtk_i2c_quirks = { | ||||
| +        .max_write_len = BYTECNT_MAX, | ||||
| +        .max_read_len = BYTECNT_MAX, | ||||
| +}; | ||||
| + | ||||
| +static void mtk_i2c_init(struct mtk_i2c *i2c) | ||||
| +{ | ||||
| +	i2c->clk_div = clk_get_rate(i2c->clk) / i2c->cur_clk; | ||||
| +	if (i2c->clk_div > CLK_DIV_MASK) | ||||
| +		i2c->clk_div = CLK_DIV_MASK; | ||||
| + | ||||
| +	mtk_i2c_reset(i2c); | ||||
| +} | ||||
| + | ||||
| +static int mtk_i2c_probe(struct platform_device *pdev) | ||||
| +{ | ||||
| +	struct resource *res; | ||||
| +	struct mtk_i2c *i2c; | ||||
| +	struct i2c_adapter *adap; | ||||
| +	const struct of_device_id *match; | ||||
| +	int ret; | ||||
| + | ||||
| +	match = of_match_device(i2c_mtk_dt_ids, &pdev->dev); | ||||
| + | ||||
| +	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||||
| +	if (!res) { | ||||
| +		dev_err(&pdev->dev, "no memory resource found\n"); | ||||
| +		return -ENODEV; | ||||
| +	} | ||||
| + | ||||
| +	i2c = devm_kzalloc(&pdev->dev, sizeof(struct mtk_i2c), GFP_KERNEL); | ||||
| +	if (!i2c) { | ||||
| +		dev_err(&pdev->dev, "failed to allocate i2c_adapter\n"); | ||||
| +		return -ENOMEM; | ||||
| +	} | ||||
| + | ||||
| +	i2c->base = devm_ioremap_resource(&pdev->dev, res); | ||||
| +	if (IS_ERR(i2c->base)) | ||||
| +		return PTR_ERR(i2c->base); | ||||
| + | ||||
| +	i2c->clk = devm_clk_get(&pdev->dev, NULL); | ||||
| +	if (IS_ERR(i2c->clk)) { | ||||
| +		dev_err(&pdev->dev, "no clock defined\n"); | ||||
| +		return -ENODEV; | ||||
| +	} | ||||
| +	clk_prepare_enable(i2c->clk); | ||||
| +	i2c->dev = &pdev->dev; | ||||
| + | ||||
| +	if (of_property_read_u32(pdev->dev.of_node, | ||||
| +				"clock-frequency", &i2c->cur_clk)) | ||||
| +		i2c->cur_clk = 100000; | ||||
| + | ||||
| +	adap = &i2c->adap; | ||||
| +	adap->owner = THIS_MODULE; | ||||
| +	adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD; | ||||
| +	adap->algo = &mtk_i2c_algo; | ||||
| +	adap->retries = 3; | ||||
| +	adap->dev.parent = &pdev->dev; | ||||
| +	i2c_set_adapdata(adap, i2c); | ||||
| +	adap->dev.of_node = pdev->dev.of_node; | ||||
| +	strlcpy(adap->name, dev_name(&pdev->dev), sizeof(adap->name)); | ||||
| +	adap->quirks = &mtk_i2c_quirks; | ||||
| + | ||||
| +	platform_set_drvdata(pdev, i2c); | ||||
| + | ||||
| +	mtk_i2c_init(i2c); | ||||
| + | ||||
| +	ret = i2c_add_adapter(adap); | ||||
| +	if (ret < 0) { | ||||
| +		dev_err(&pdev->dev, "failed to add adapter\n"); | ||||
| +		clk_disable_unprepare(i2c->clk); | ||||
| +		return ret; | ||||
| +	} | ||||
| + | ||||
| +	dev_info(&pdev->dev, "clock %uKHz, re-start not support\n", | ||||
| +			i2c->cur_clk/1000); | ||||
| + | ||||
| +	return ret; | ||||
| +} | ||||
| + | ||||
| +static int mtk_i2c_remove(struct platform_device *pdev) | ||||
| +{ | ||||
| +	struct mtk_i2c *i2c = platform_get_drvdata(pdev); | ||||
| + | ||||
| +	i2c_del_adapter(&i2c->adap); | ||||
| +	clk_disable_unprepare(i2c->clk); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static struct platform_driver mtk_i2c_driver = { | ||||
| +	.probe		= mtk_i2c_probe, | ||||
| +	.remove		= mtk_i2c_remove, | ||||
| +	.driver		= { | ||||
| +		.owner	= THIS_MODULE, | ||||
| +		.name	= "i2c-mt7621", | ||||
| +		.of_match_table = i2c_mtk_dt_ids, | ||||
| +	}, | ||||
| +}; | ||||
| + | ||||
| +static int __init i2c_mtk_init (void) | ||||
| +{ | ||||
| +	return platform_driver_register(&mtk_i2c_driver); | ||||
| +} | ||||
| +subsys_initcall(i2c_mtk_init); | ||||
| + | ||||
| +static void __exit i2c_mtk_exit (void) | ||||
| +{ | ||||
| +	platform_driver_unregister(&mtk_i2c_driver); | ||||
| +} | ||||
| +module_exit(i2c_mtk_exit); | ||||
| + | ||||
| +MODULE_AUTHOR("Steven Liu <steven_liu@mediatek.com>"); | ||||
| +MODULE_DESCRIPTION("MT7621 I2c host driver"); | ||||
| +MODULE_LICENSE("GPL"); | ||||
| +MODULE_ALIAS("platform:MT7621-I2C"); | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1046
									
								
								target/linux/ramips/patches-4.9/0048-asoc-add-mt7620-support.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1046
									
								
								target/linux/ramips/patches-4.9/0048-asoc-add-mt7620-support.patch
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,22 @@ | ||||
| From a7eb46e0ea4a11e4dfb56ab129bf816d1059a6c5 Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <blogic@openwrt.org> | ||||
| Date: Mon, 7 Dec 2015 17:31:08 +0100 | ||||
| Subject: [PATCH 51/53] serial: add ugly custom baud rate hack | ||||
|  | ||||
| Signed-off-by: John Crispin <blogic@openwrt.org> | ||||
| --- | ||||
|  drivers/tty/serial/serial_core.c |    3 +++ | ||||
|  1 file changed, 3 insertions(+) | ||||
|  | ||||
| --- a/drivers/tty/serial/serial_core.c | ||||
| +++ b/drivers/tty/serial/serial_core.c | ||||
| @@ -388,6 +388,9 @@ uart_get_baud_rate(struct uart_port *por | ||||
|  		break; | ||||
|  	} | ||||
|   | ||||
| +	if (tty_termios_baud_rate(termios) == 2500000) | ||||
| +		return 250000; | ||||
| + | ||||
|  	for (try = 0; try < 2; try++) { | ||||
|  		baud = tty_termios_baud_rate(termios); | ||||
|   | ||||
| @@ -0,0 +1,217 @@ | ||||
| From fc8f96309c21c1bc3276427309cd7d361347d66e Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <blogic@openwrt.org> | ||||
| Date: Mon, 7 Dec 2015 17:16:50 +0100 | ||||
| Subject: [PATCH 52/53] pwm: add mediatek support | ||||
|  | ||||
| Signed-off-by: John Crispin <blogic@openwrt.org> | ||||
| --- | ||||
|  drivers/pwm/Kconfig        |    9 +++ | ||||
|  drivers/pwm/Makefile       |    1 + | ||||
|  drivers/pwm/pwm-mediatek.c |  173 ++++++++++++++++++++++++++++++++++++++++++++ | ||||
|  3 files changed, 183 insertions(+) | ||||
|  create mode 100644 drivers/pwm/pwm-mediatek.c | ||||
|  | ||||
| --- a/drivers/pwm/Kconfig | ||||
| +++ b/drivers/pwm/Kconfig | ||||
| @@ -282,6 +282,15 @@ config PWM_MTK_DISP | ||||
|  	  To compile this driver as a module, choose M here: the module | ||||
|  	  will be called pwm-mtk-disp. | ||||
|   | ||||
| +config PWM_MEDIATEK | ||||
| +	tristate "Mediatek PWM support" | ||||
| +	depends on RALINK && OF | ||||
| +	help | ||||
| +	  Generic PWM framework driver for Mediatek ARM SoC. | ||||
| + | ||||
| +	  To compile this driver as a module, choose M here: the module | ||||
| +	  will be called pwm-mxs. | ||||
| + | ||||
|  config PWM_MXS | ||||
|  	tristate "Freescale MXS PWM support" | ||||
|  	depends on ARCH_MXS && OF | ||||
| --- a/drivers/pwm/Makefile | ||||
| +++ b/drivers/pwm/Makefile | ||||
| @@ -25,6 +25,7 @@ obj-$(CONFIG_PWM_LPSS)		+= pwm-lpss.o | ||||
|  obj-$(CONFIG_PWM_LPSS_PCI)	+= pwm-lpss-pci.o | ||||
|  obj-$(CONFIG_PWM_LPSS_PLATFORM)	+= pwm-lpss-platform.o | ||||
|  obj-$(CONFIG_PWM_MESON)		+= pwm-meson.o | ||||
| +obj-$(CONFIG_PWM_MEDIATEK)	+= pwm-mediatek.o | ||||
|  obj-$(CONFIG_PWM_MTK_DISP)	+= pwm-mtk-disp.o | ||||
|  obj-$(CONFIG_PWM_MXS)		+= pwm-mxs.o | ||||
|  obj-$(CONFIG_PWM_OMAP_DMTIMER)	+= pwm-omap-dmtimer.o | ||||
| --- /dev/null | ||||
| +++ b/drivers/pwm/pwm-mediatek.c | ||||
| @@ -0,0 +1,173 @@ | ||||
| +/* | ||||
| + * Mediatek Pulse Width Modulator driver | ||||
| + * | ||||
| + * Copyright (C) 2015 John Crispin <blogic@openwrt.org> | ||||
| + * | ||||
| + * This file is licensed under the terms of the GNU General Public | ||||
| + * License version 2. This program is licensed "as is" without any | ||||
| + * warranty of any kind, whether express or implied. | ||||
| + */ | ||||
| + | ||||
| +#include <linux/err.h> | ||||
| +#include <linux/io.h> | ||||
| +#include <linux/ioport.h> | ||||
| +#include <linux/kernel.h> | ||||
| +#include <linux/module.h> | ||||
| +#include <linux/of.h> | ||||
| +#include <linux/platform_device.h> | ||||
| +#include <linux/pwm.h> | ||||
| +#include <linux/slab.h> | ||||
| +#include <linux/types.h> | ||||
| + | ||||
| +#define NUM_PWM		4 | ||||
| + | ||||
| +/* PWM registers and bits definitions */ | ||||
| +#define PWMCON			0x00 | ||||
| +#define PWMHDUR			0x04 | ||||
| +#define PWMLDUR			0x08 | ||||
| +#define PWMGDUR			0x0c | ||||
| +#define PWMWAVENUM		0x28 | ||||
| +#define PWMDWIDTH		0x2c | ||||
| +#define PWMTHRES		0x30 | ||||
| + | ||||
| +/** | ||||
| + * struct mtk_pwm_chip - struct representing pwm chip | ||||
| + * | ||||
| + * @mmio_base: base address of pwm chip | ||||
| + * @chip: linux pwm chip representation | ||||
| + */ | ||||
| +struct mtk_pwm_chip { | ||||
| +	void __iomem *mmio_base; | ||||
| +	struct pwm_chip chip; | ||||
| +}; | ||||
| + | ||||
| +static inline struct mtk_pwm_chip *to_mtk_pwm_chip(struct pwm_chip *chip) | ||||
| +{ | ||||
| +	return container_of(chip, struct mtk_pwm_chip, chip); | ||||
| +} | ||||
| + | ||||
| +static inline u32 mtk_pwm_readl(struct mtk_pwm_chip *chip, unsigned int num, | ||||
| +				  unsigned long offset) | ||||
| +{ | ||||
| +	return ioread32(chip->mmio_base + 0x10 + (num * 0x40) + offset); | ||||
| +} | ||||
| + | ||||
| +static inline void mtk_pwm_writel(struct mtk_pwm_chip *chip, | ||||
| +				    unsigned int num, unsigned long offset, | ||||
| +				    unsigned long val) | ||||
| +{ | ||||
| +	iowrite32(val, chip->mmio_base + 0x10 + (num * 0x40) + offset); | ||||
| +} | ||||
| + | ||||
| +static int mtk_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, | ||||
| +			    int duty_ns, int period_ns) | ||||
| +{ | ||||
| +	struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip); | ||||
| +	u32 resolution = 100 / 4; | ||||
| +	u32 clkdiv = 0; | ||||
| + | ||||
| +	while (period_ns / resolution  > 8191) { | ||||
| +		clkdiv++; | ||||
| +		resolution *= 2; | ||||
| +	} | ||||
| + | ||||
| +	if (clkdiv > 7) | ||||
| +		return -1; | ||||
| + | ||||
| +	mtk_pwm_writel(pc, pwm->hwpwm, PWMCON, BIT(15) | BIT(3) | clkdiv); | ||||
| +	mtk_pwm_writel(pc, pwm->hwpwm, PWMDWIDTH, period_ns / resolution); | ||||
| +	mtk_pwm_writel(pc, pwm->hwpwm, PWMTHRES, duty_ns / resolution); | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static int mtk_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) | ||||
| +{ | ||||
| +	struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip); | ||||
| +	u32 val; | ||||
| + | ||||
| +	val = ioread32(pc->mmio_base); | ||||
| +	val |= BIT(pwm->hwpwm); | ||||
| +	iowrite32(val, pc->mmio_base); | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static void mtk_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) | ||||
| +{ | ||||
| +	struct mtk_pwm_chip *pc = to_mtk_pwm_chip(chip); | ||||
| +	u32 val; | ||||
| + | ||||
| +	val = ioread32(pc->mmio_base); | ||||
| +	val &= ~BIT(pwm->hwpwm); | ||||
| +	iowrite32(val, pc->mmio_base); | ||||
| +} | ||||
| + | ||||
| +static const struct pwm_ops mtk_pwm_ops = { | ||||
| +	.config = mtk_pwm_config, | ||||
| +	.enable = mtk_pwm_enable, | ||||
| +	.disable = mtk_pwm_disable, | ||||
| +	.owner = THIS_MODULE, | ||||
| +}; | ||||
| + | ||||
| +static int mtk_pwm_probe(struct platform_device *pdev) | ||||
| +{ | ||||
| +	struct mtk_pwm_chip *pc; | ||||
| +	struct resource *r; | ||||
| +	int ret; | ||||
| + | ||||
| +	pc = devm_kzalloc(&pdev->dev, sizeof(*pc), GFP_KERNEL); | ||||
| +	if (!pc) | ||||
| +		return -ENOMEM; | ||||
| + | ||||
| +	r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||||
| +	pc->mmio_base = devm_ioremap_resource(&pdev->dev, r); | ||||
| +	if (IS_ERR(pc->mmio_base)) | ||||
| +		return PTR_ERR(pc->mmio_base); | ||||
| + | ||||
| +	platform_set_drvdata(pdev, pc); | ||||
| + | ||||
| +	pc->chip.dev = &pdev->dev; | ||||
| +	pc->chip.ops = &mtk_pwm_ops; | ||||
| +	pc->chip.base = -1; | ||||
| +	pc->chip.npwm = NUM_PWM; | ||||
| + | ||||
| +	ret = pwmchip_add(&pc->chip); | ||||
| +	if (ret < 0) | ||||
| +		dev_err(&pdev->dev, "pwmchip_add() failed: %d\n", ret); | ||||
| + | ||||
| +	return ret; | ||||
| +} | ||||
| + | ||||
| +static int mtk_pwm_remove(struct platform_device *pdev) | ||||
| +{ | ||||
| +	struct mtk_pwm_chip *pc = platform_get_drvdata(pdev); | ||||
| +	int i; | ||||
| + | ||||
| +	for (i = 0; i < NUM_PWM; i++) | ||||
| +		pwm_disable(&pc->chip.pwms[i]); | ||||
| + | ||||
| +	return pwmchip_remove(&pc->chip); | ||||
| +} | ||||
| + | ||||
| +static const struct of_device_id mtk_pwm_of_match[] = { | ||||
| +	{ .compatible = "mediatek,mt7628-pwm" }, | ||||
| +	{ } | ||||
| +}; | ||||
| + | ||||
| +MODULE_DEVICE_TABLE(of, mtk_pwm_of_match); | ||||
| + | ||||
| +static struct platform_driver mtk_pwm_driver = { | ||||
| +	.driver = { | ||||
| +		.name = "mtk-pwm", | ||||
| +		.owner = THIS_MODULE, | ||||
| +		.of_match_table = mtk_pwm_of_match, | ||||
| +	}, | ||||
| +	.probe = mtk_pwm_probe, | ||||
| +	.remove = mtk_pwm_remove, | ||||
| +}; | ||||
| + | ||||
| +module_platform_driver(mtk_pwm_driver); | ||||
| + | ||||
| +MODULE_LICENSE("GPL"); | ||||
| +MODULE_AUTHOR("John Crispin <blogic@openwrt.org>"); | ||||
| +MODULE_ALIAS("platform:mtk-pwm"); | ||||
| @@ -0,0 +1,123 @@ | ||||
| --- a/drivers/mtd/spi-nor/spi-nor.c | ||||
| +++ b/drivers/mtd/spi-nor/spi-nor.c | ||||
| @@ -1381,6 +1381,66 @@ write_err: | ||||
|  	return ret; | ||||
|  } | ||||
|   | ||||
| +static int spi_nor_chunked_write(struct mtd_info *mtd, loff_t _to, size_t _len, | ||||
| +				 size_t *_retlen, const u_char *_buf) | ||||
| +{ | ||||
| +	struct spi_nor *nor = mtd_to_spi_nor(mtd); | ||||
| +	int chunk_size; | ||||
| +	int retlen = 0; | ||||
| +	int ret; | ||||
| + | ||||
| +	chunk_size = nor->chunk_size; | ||||
| +	if (!chunk_size) | ||||
| +		chunk_size = _len; | ||||
| + | ||||
| +	if (nor->addr_width > 3) | ||||
| +		chunk_size -= nor->addr_width - 3; | ||||
| + | ||||
| +	while (retlen < _len) { | ||||
| +		size_t len = min_t(int, chunk_size, _len - retlen); | ||||
| +		const u_char *buf = _buf + retlen; | ||||
| +		loff_t to = _to + retlen; | ||||
| + | ||||
| +		if (nor->flags & SNOR_F_SST) | ||||
| +			ret = sst_write(mtd, to, len, &retlen, buf); | ||||
| +		else | ||||
| +			ret = spi_nor_write(mtd, to, len, &retlen, buf); | ||||
| +		if (ret) | ||||
| +			return ret; | ||||
| +	} | ||||
| + | ||||
| +	*_retlen += retlen; | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static int spi_nor_chunked_read(struct mtd_info *mtd, loff_t _from, size_t _len, | ||||
| +				size_t *_retlen, u_char *_buf) | ||||
| +{ | ||||
| +	struct spi_nor *nor = mtd_to_spi_nor(mtd); | ||||
| +	int chunk_size; | ||||
| +	int ret; | ||||
| + | ||||
| +	chunk_size = nor->chunk_size; | ||||
| +	if (!chunk_size) | ||||
| +		chunk_size = _len; | ||||
| + | ||||
| +	*_retlen = 0; | ||||
| +	while (*_retlen < _len) { | ||||
| +		size_t len = min_t(int, chunk_size, _len - *_retlen); | ||||
| +		u_char *buf = _buf + *_retlen; | ||||
| +		loff_t from = _from + *_retlen; | ||||
| +		int retlen = 0; | ||||
| + | ||||
| +		ret = spi_nor_read(mtd, from, len, &retlen, buf); | ||||
| +		if (ret) | ||||
| +			return ret; | ||||
| + | ||||
| +		*_retlen += retlen; | ||||
| +	} | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
|  static int macronix_quad_enable(struct spi_nor *nor) | ||||
|  { | ||||
|  	int ret, val; | ||||
| @@ -1623,10 +1683,12 @@ int spi_nor_scan(struct spi_nor *nor, co | ||||
|  	} | ||||
|   | ||||
|  	/* sst nor chips use AAI word program */ | ||||
| -	if (info->flags & SST_WRITE) | ||||
| +	if (info->flags & SST_WRITE) { | ||||
|  		mtd->_write = sst_write; | ||||
| -	else | ||||
| +		nor->flags |= SNOR_F_SST; | ||||
| +	} else { | ||||
|  		mtd->_write = spi_nor_write; | ||||
| +	} | ||||
|   | ||||
|  	if (info->flags & USE_FSR) | ||||
|  		nor->flags |= SNOR_F_USE_FSR; | ||||
| @@ -1656,11 +1718,20 @@ int spi_nor_scan(struct spi_nor *nor, co | ||||
|  	mtd->writebufsize = nor->page_size; | ||||
|   | ||||
|  	if (np) { | ||||
| +		u32 val; | ||||
| + | ||||
|  		/* If we were instantiated by DT, use it */ | ||||
|  		if (of_property_read_bool(np, "m25p,fast-read")) | ||||
|  			nor->flash_read = SPI_NOR_FAST; | ||||
|  		else | ||||
|  			nor->flash_read = SPI_NOR_NORMAL; | ||||
| + | ||||
| +		if (!of_property_read_u32(np, "m25p,chunked-io", &val)) { | ||||
| +			dev_info(dev, "using chunked io (size=%d)\n", val); | ||||
| +			mtd->_read = spi_nor_chunked_read; | ||||
| +			mtd->_write = spi_nor_chunked_write; | ||||
| +			nor->chunk_size = val; | ||||
| +		} | ||||
|  	} else { | ||||
|  		/* If we weren't instantiated by DT, default to fast-read */ | ||||
|  		nor->flash_read = SPI_NOR_FAST; | ||||
| --- a/include/linux/mtd/spi-nor.h | ||||
| +++ b/include/linux/mtd/spi-nor.h | ||||
| @@ -141,6 +141,7 @@ enum spi_nor_option_flags { | ||||
|  	SNOR_F_NO_OP_CHIP_ERASE	= BIT(2), | ||||
|  	SNOR_F_S3AN_ADDR_DEFAULT = BIT(3), | ||||
|  	SNOR_F_READY_XSR_RDY	= BIT(4), | ||||
| +	SNOR_F_SST		= BIT(5), | ||||
|  }; | ||||
|   | ||||
|  /** | ||||
| @@ -180,6 +181,7 @@ struct spi_nor { | ||||
|  	struct mutex		lock; | ||||
|  	struct device		*dev; | ||||
|  	u32			page_size; | ||||
| +	u16			chunk_size; | ||||
|  	u8			addr_width; | ||||
|  	u8			erase_opcode; | ||||
|  	u8			read_opcode; | ||||
| @@ -0,0 +1,12 @@ | ||||
| --- a/arch/mips/include/asm/mips-cm.h | ||||
| +++ b/arch/mips/include/asm/mips-cm.h | ||||
| @@ -239,8 +239,7 @@ BUILD_CM_Cx_R_(tcid_8_priority,	0x80) | ||||
|  #define CM_GCR_BASE_GCRBASE_MSK			(_ULCAST_(0x1ffff) << 15) | ||||
|  #define CM_GCR_BASE_CMDEFTGT_SHF		0 | ||||
|  #define CM_GCR_BASE_CMDEFTGT_MSK		(_ULCAST_(0x3) << 0) | ||||
| -#define  CM_GCR_BASE_CMDEFTGT_DISABLED		0 | ||||
| -#define  CM_GCR_BASE_CMDEFTGT_MEM		1 | ||||
| +#define  CM_GCR_BASE_CMDEFTGT_MEM		0 | ||||
|  #define  CM_GCR_BASE_CMDEFTGT_IOCU0		2 | ||||
|  #define  CM_GCR_BASE_CMDEFTGT_IOCU1		3 | ||||
|   | ||||
| @@ -0,0 +1,15 @@ | ||||
| --- a/arch/mips/ralink/clk.c | ||||
| +++ b/arch/mips/ralink/clk.c | ||||
| @@ -62,6 +62,12 @@ int clk_set_rate(struct clk *clk, unsign | ||||
|  } | ||||
|  EXPORT_SYMBOL_GPL(clk_set_rate); | ||||
|   | ||||
| +long clk_round_rate(struct clk *clk, unsigned long rate) | ||||
| +{ | ||||
| +	return -1; | ||||
| +} | ||||
| +EXPORT_SYMBOL_GPL(clk_round_rate); | ||||
| + | ||||
|  void __init plat_time_init(void) | ||||
|  { | ||||
|  	struct clk *clk; | ||||
| @@ -0,0 +1,10 @@ | ||||
| --- a/arch/mips/ralink/Kconfig | ||||
| +++ b/arch/mips/ralink/Kconfig | ||||
| @@ -51,6 +51,7 @@ choice | ||||
|  		select SYS_SUPPORTS_MULTITHREADING | ||||
|  		select SYS_SUPPORTS_SMP | ||||
|  		select SYS_SUPPORTS_MIPS_CPS | ||||
| +		select SYS_SUPPORTS_HIGHMEM | ||||
|  		select MIPS_GIC | ||||
|  		select COMMON_CLK | ||||
|  		select CLKSRC_MIPS_GIC | ||||
| @@ -0,0 +1,14 @@ | ||||
| --- a/drivers/usb/host/Kconfig | ||||
| +++ b/drivers/usb/host/Kconfig | ||||
| @@ -45,9 +45,9 @@ config USB_XHCI_PLATFORM | ||||
|  	  If unsure, say N. | ||||
|   | ||||
|  config USB_XHCI_MTK | ||||
| -	tristate "xHCI support for Mediatek MT65xx" | ||||
| +	tristate "xHCI support for Mediatek MT65xx/MT7621" | ||||
|  	select MFD_SYSCON | ||||
| -	depends on ARCH_MEDIATEK || COMPILE_TEST | ||||
| +	depends on SOC_MT7621 || ARCH_MEDIATEK || COMPILE_TEST | ||||
|  	---help--- | ||||
|  	  Say 'Y' to enable the support for the xHCI host controller | ||||
|  	  found in Mediatek MT65xx SoCs. | ||||
							
								
								
									
										30
									
								
								target/linux/ramips/patches-4.9/0068-fix-ralink-prom.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								target/linux/ramips/patches-4.9/0068-fix-ralink-prom.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| --- a/arch/mips/ralink/prom.c | ||||
| +++ b/arch/mips/ralink/prom.c | ||||
| @@ -30,8 +30,10 @@ const char *get_system_type(void) | ||||
|  	return soc_info.sys_type; | ||||
|  } | ||||
|   | ||||
| -static __init void prom_init_cmdline(int argc, char **argv) | ||||
| +static __init void prom_init_cmdline(void) | ||||
|  { | ||||
| +	int argc; | ||||
| +	char **argv; | ||||
|  	int i; | ||||
|   | ||||
|  	pr_debug("prom: fw_arg0=%08x fw_arg1=%08x fw_arg2=%08x fw_arg3=%08x\n", | ||||
| @@ -60,14 +62,11 @@ static __init void prom_init_cmdline(int | ||||
|   | ||||
|  void __init prom_init(void) | ||||
|  { | ||||
| -	int argc; | ||||
| -	char **argv; | ||||
| - | ||||
|  	prom_soc_init(&soc_info); | ||||
|   | ||||
|  	pr_info("SoC Type: %s\n", get_system_type()); | ||||
|   | ||||
| -	prom_init_cmdline(argc, argv); | ||||
| +	prom_init_cmdline(); | ||||
|  } | ||||
|   | ||||
|  void __init prom_free_prom_memory(void) | ||||
| @@ -0,0 +1,15 @@ | ||||
| --- a/drivers/usb/dwc2/platform.c | ||||
| +++ b/drivers/usb/dwc2/platform.c | ||||
| @@ -616,6 +616,12 @@ static int dwc2_driver_probe(struct plat | ||||
|  	if (retval) | ||||
|  		return retval; | ||||
|   | ||||
| +	/* Enable USB port before any regs access */ | ||||
| +	if (dwc2_readl(hsotg->regs + PCGCTL) & 0x0f) { | ||||
| +		dwc2_writel(0x00, hsotg->regs + PCGCTL); | ||||
| +		/* TODO: mdelay(25) here? vendor driver don't use it */ | ||||
| +	} | ||||
| + | ||||
|  	retval = dwc2_get_dr_mode(hsotg); | ||||
|  	if (retval) | ||||
|  		goto error; | ||||
							
								
								
									
										77
									
								
								target/linux/ramips/patches-4.9/0085-pinmux-util.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								target/linux/ramips/patches-4.9/0085-pinmux-util.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | ||||
| --- a/arch/mips/ralink/mt7620.c | ||||
| +++ b/arch/mips/ralink/mt7620.c | ||||
| @@ -176,7 +176,7 @@ static struct rt2880_pmx_func spi_cs1_gr | ||||
|   | ||||
|  static struct rt2880_pmx_func spis_grp_mt7628[] = { | ||||
|  	FUNC("pwm_uart2", 3, 14, 4), | ||||
| -	FUNC("util", 2, 14, 4), | ||||
| +	FUNC("utif", 2, 14, 4), | ||||
|  	FUNC("gpio", 1, 14, 4), | ||||
|  	FUNC("spis", 0, 14, 4), | ||||
|  }; | ||||
| @@ -190,28 +190,28 @@ static struct rt2880_pmx_func gpio_grp_m | ||||
|   | ||||
|  static struct rt2880_pmx_func p4led_kn_grp_mt7628[] = { | ||||
|  	FUNC("jtag", 3, 30, 1), | ||||
| -	FUNC("util", 2, 30, 1), | ||||
| +	FUNC("utif", 2, 30, 1), | ||||
|  	FUNC("gpio", 1, 30, 1), | ||||
|  	FUNC("p4led_kn", 0, 30, 1), | ||||
|  }; | ||||
|   | ||||
|  static struct rt2880_pmx_func p3led_kn_grp_mt7628[] = { | ||||
|  	FUNC("jtag", 3, 31, 1), | ||||
| -	FUNC("util", 2, 31, 1), | ||||
| +	FUNC("utif", 2, 31, 1), | ||||
|  	FUNC("gpio", 1, 31, 1), | ||||
|  	FUNC("p3led_kn", 0, 31, 1), | ||||
|  }; | ||||
|   | ||||
|  static struct rt2880_pmx_func p2led_kn_grp_mt7628[] = { | ||||
|  	FUNC("jtag", 3, 32, 1), | ||||
| -	FUNC("util", 2, 32, 1), | ||||
| +	FUNC("utif", 2, 32, 1), | ||||
|  	FUNC("gpio", 1, 32, 1), | ||||
|  	FUNC("p2led_kn", 0, 32, 1), | ||||
|  }; | ||||
|   | ||||
|  static struct rt2880_pmx_func p1led_kn_grp_mt7628[] = { | ||||
|  	FUNC("jtag", 3, 33, 1), | ||||
| -	FUNC("util", 2, 33, 1), | ||||
| +	FUNC("utif", 2, 33, 1), | ||||
|  	FUNC("gpio", 1, 33, 1), | ||||
|  	FUNC("p1led_kn", 0, 33, 1), | ||||
|  }; | ||||
| @@ -232,28 +232,28 @@ static struct rt2880_pmx_func wled_kn_gr | ||||
|   | ||||
|  static struct rt2880_pmx_func p4led_an_grp_mt7628[] = { | ||||
|  	FUNC("jtag", 3, 39, 1), | ||||
| -	FUNC("util", 2, 39, 1), | ||||
| +	FUNC("utif", 2, 39, 1), | ||||
|  	FUNC("gpio", 1, 39, 1), | ||||
|  	FUNC("p4led_an", 0, 39, 1), | ||||
|  }; | ||||
|   | ||||
|  static struct rt2880_pmx_func p3led_an_grp_mt7628[] = { | ||||
|  	FUNC("jtag", 3, 40, 1), | ||||
| -	FUNC("util", 2, 40, 1), | ||||
| +	FUNC("utif", 2, 40, 1), | ||||
|  	FUNC("gpio", 1, 40, 1), | ||||
|  	FUNC("p3led_an", 0, 40, 1), | ||||
|  }; | ||||
|   | ||||
|  static struct rt2880_pmx_func p2led_an_grp_mt7628[] = { | ||||
|  	FUNC("jtag", 3, 41, 1), | ||||
| -	FUNC("util", 2, 41, 1), | ||||
| +	FUNC("utif", 2, 41, 1), | ||||
|  	FUNC("gpio", 1, 41, 1), | ||||
|  	FUNC("p2led_an", 0, 41, 1), | ||||
|  }; | ||||
|   | ||||
|  static struct rt2880_pmx_func p1led_an_grp_mt7628[] = { | ||||
|  	FUNC("jtag", 3, 42, 1), | ||||
| -	FUNC("util", 2, 42, 1), | ||||
| +	FUNC("utif", 2, 42, 1), | ||||
|  	FUNC("gpio", 1, 42, 1), | ||||
|  	FUNC("p1led_an", 0, 42, 1), | ||||
|  }; | ||||
							
								
								
									
										41
									
								
								target/linux/ramips/patches-4.9/0090-ethernet.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								target/linux/ramips/patches-4.9/0090-ethernet.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| From b6f779ea9c329451b89404583b45b9eb00155b32 Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <blogic@openwrt.org> | ||||
| Date: Wed, 18 Nov 2015 03:58:26 +0100 | ||||
| Subject: [PATCH 510/513] net-next: mediatek: add Kconfig and Makefile | ||||
|  | ||||
| This patch adds the Makefile and Kconfig required to make the driver build. | ||||
|  | ||||
| Signed-off-by: John Crispin <blogic@openwrt.org> | ||||
| Signed-off-by: Felix Fietkau <nbd@nbd.name> | ||||
| Signed-off-by: Michael Lee <igvtee@gmail.com> | ||||
| --- | ||||
|  drivers/net/ethernet/Kconfig           |    1 + | ||||
|  drivers/net/ethernet/Makefile          |    1 + | ||||
|  drivers/net/ethernet/mtk/Kconfig  |   62 ++++++++++++++++++++++++++++++++ | ||||
|  drivers/net/ethernet/mtk/Makefile |   20 +++++++++++ | ||||
|  4 files changed, 84 insertions(+) | ||||
|  create mode 100644 drivers/net/ethernet/mtk/Kconfig | ||||
|  create mode 100644 drivers/net/ethernet/mtk/Makefile | ||||
|  | ||||
| --- a/drivers/net/ethernet/Kconfig | ||||
| +++ b/drivers/net/ethernet/Kconfig | ||||
| @@ -107,7 +107,7 @@ | ||||
|  	  Support for the MII0 inside the Lantiq SoC | ||||
|   | ||||
|  source "drivers/net/ethernet/marvell/Kconfig" | ||||
| -source "drivers/net/ethernet/mediatek/Kconfig" | ||||
| +source "drivers/net/ethernet/mtk/Kconfig" | ||||
|  source "drivers/net/ethernet/mellanox/Kconfig" | ||||
|  source "drivers/net/ethernet/micrel/Kconfig" | ||||
|  source "drivers/net/ethernet/microchip/Kconfig" | ||||
| --- a/drivers/net/ethernet/Makefile | ||||
| +++ b/drivers/net/ethernet/Makefile | ||||
| @@ -47,7 +47,7 @@ | ||||
|  obj-$(CONFIG_KORINA) += korina.o | ||||
|  obj-$(CONFIG_LANTIQ_ETOP) += lantiq_etop.o | ||||
|  obj-$(CONFIG_NET_VENDOR_MARVELL) += marvell/ | ||||
| -obj-$(CONFIG_NET_VENDOR_MEDIATEK) += mediatek/ | ||||
| +obj-$(CONFIG_NET_VENDOR_MEDIATEK) += mtk/ | ||||
|  obj-$(CONFIG_NET_VENDOR_MELLANOX) += mellanox/ | ||||
|  obj-$(CONFIG_NET_VENDOR_MICREL) += micrel/ | ||||
|  obj-$(CONFIG_NET_VENDOR_MICROCHIP) += microchip/ | ||||
							
								
								
									
										19
									
								
								target/linux/ramips/patches-4.9/0099-pci-mt7620.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								target/linux/ramips/patches-4.9/0099-pci-mt7620.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | ||||
| --- a/arch/mips/pci/pci-mt7620.c | ||||
| +++ b/arch/mips/pci/pci-mt7620.c | ||||
| @@ -33,7 +33,6 @@ | ||||
|  #define RALINK_GPIOMODE			0x60 | ||||
|   | ||||
|  #define PPLL_CFG1			0x9c | ||||
| -#define PDRV_SW_SET			BIT(23) | ||||
|   | ||||
|  #define PPLL_DRV			0xa0 | ||||
|  #define PDRV_SW_SET			(1<<31) | ||||
| @@ -121,7 +120,7 @@ | ||||
|  		else | ||||
|  			break; | ||||
|  		if (retry++ > WAITRETRY_MAX) { | ||||
| -			printk(KERN_WARN "PCIE-PHY retry failed.\n"); | ||||
| +			pr_warn("PCIE-PHY retry failed.\n"); | ||||
|  			return -1; | ||||
|  		} | ||||
|  	} | ||||
							
								
								
									
										66
									
								
								target/linux/ramips/patches-4.9/0100-prom_fixes.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								target/linux/ramips/patches-4.9/0100-prom_fixes.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| From 67b7bff0fd364c194e653f69baa623ba2141bd4c Mon Sep 17 00:00:00 2001 | ||||
| From: John Crispin <blogic@openwrt.org> | ||||
| Date: Mon, 4 Aug 2014 18:46:02 +0200 | ||||
| Subject: [PATCH 07/53] MIPS: ralink: copy the commandline from the devicetree | ||||
|  | ||||
| Signed-off-by: John Crispin <blogic@openwrt.org> | ||||
| --- | ||||
|  arch/mips/ralink/of.c |    2 ++ | ||||
|  1 file changed, 2 insertions(+) | ||||
|  | ||||
| --- a/arch/mips/ralink/of.c | ||||
| +++ b/arch/mips/ralink/of.c | ||||
| @@ -3,7 +3,7 @@ | ||||
|   * under the terms of the GNU General Public License version 2 as published | ||||
|   * by the Free Software Foundation. | ||||
|   * | ||||
| - * Copyright (C) 2008 Imre Kaloz <kaloz@openwrt.org> | ||||
| + * Copyright (C) 2008-2014 Imre Kaloz <kaloz@openwrt.org> | ||||
|   * Copyright (C) 2008-2009 Gabor Juhos <juhosg@openwrt.org> | ||||
|   * Copyright (C) 2013 John Crispin <john@phrozen.org> | ||||
|   */ | ||||
| @@ -66,6 +66,19 @@ static int __init early_init_dt_find_mem | ||||
|  	return 0; | ||||
|  } | ||||
|   | ||||
| +static int chosen_dtb; | ||||
| + | ||||
| +static int __init early_init_dt_find_chosen(unsigned long node, const char *uname, | ||||
| +				     int depth, void *data) | ||||
| +{ | ||||
| +	if (depth == 1 && !strcmp(uname, "chosen")) | ||||
| +		chosen_dtb = 1; | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +extern struct boot_param_header __image_dtb; | ||||
| + | ||||
|  void __init plat_mem_setup(void) | ||||
|  { | ||||
|  	set_io_port_base(KSEG1); | ||||
| @@ -74,7 +87,11 @@ void __init plat_mem_setup(void) | ||||
|  	 * Load the builtin devicetree. This causes the chosen node to be | ||||
|  	 * parsed resulting in our memory appearing | ||||
|  	 */ | ||||
| -	__dt_setup_arch(__dtb_start); | ||||
| +	__dt_setup_arch(&__image_dtb); | ||||
| + | ||||
| +	of_scan_flat_dt(early_init_dt_find_chosen, NULL); | ||||
| +	if (chosen_dtb) | ||||
| +		strlcpy(arcs_cmdline, boot_command_line, COMMAND_LINE_SIZE); | ||||
|   | ||||
|  	of_scan_flat_dt(early_init_dt_find_memory, NULL); | ||||
|  	if (memory_dtb) | ||||
| --- a/arch/mips/kernel/head.S | ||||
| +++ b/arch/mips/kernel/head.S | ||||
| @@ -85,6 +85,9 @@ EXPORT(__image_cmdline) | ||||
|  	.fill	0x400 | ||||
|  #endif /* CONFIG_IMAGE_CMDLINE_HACK */ | ||||
|   | ||||
| +	.ascii  "OWRTDTB:" | ||||
| +	EXPORT(__image_dtb) | ||||
| +	.fill   0x4000 | ||||
|  	__REF | ||||
|   | ||||
|  NESTED(kernel_entry, 16, sp)			# kernel entry point | ||||
| @@ -0,0 +1,11 @@ | ||||
| --- a/arch/mips/ralink/mt7621.c | ||||
| +++ b/arch/mips/ralink/mt7621.c | ||||
| @@ -181,7 +181,7 @@ void prom_soc_init(struct ralink_soc_inf | ||||
|  	} else { | ||||
|  		panic("mt7621: unknown SoC, n0:%08x n1:%08x\n", n0, n1); | ||||
|  	} | ||||
| - | ||||
| +	ralink_soc = MT762X_SOC_MT7621AT; | ||||
|  	rev = __raw_readl(sysc + SYSC_REG_CHIP_REV); | ||||
|   | ||||
|  	snprintf(soc_info->sys_type, RAMIPS_SYS_TYPE_LEN, | ||||
							
								
								
									
										97
									
								
								target/linux/ramips/patches-4.9/0200-linkit_bootstrap.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								target/linux/ramips/patches-4.9/0200-linkit_bootstrap.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | ||||
| --- a/drivers/misc/Makefile | ||||
| +++ b/drivers/misc/Makefile | ||||
| @@ -54,6 +54,7 @@ obj-$(CONFIG_ECHO)		+= echo/ | ||||
|  obj-$(CONFIG_VEXPRESS_SYSCFG)	+= vexpress-syscfg.o | ||||
|  obj-$(CONFIG_CXL_BASE)		+= cxl/ | ||||
|  obj-$(CONFIG_PANEL)             += panel.o | ||||
| +obj-$(CONFIG_SOC_MT7620)	+= linkit.o | ||||
|   | ||||
|  lkdtm-$(CONFIG_LKDTM)		+= lkdtm_core.o | ||||
|  lkdtm-$(CONFIG_LKDTM)		+= lkdtm_bugs.o | ||||
| --- /dev/null | ||||
| +++ b/drivers/misc/linkit.c | ||||
| @@ -0,0 +1,84 @@ | ||||
| +/* | ||||
| + *  This program is free software; you can redistribute it and/or modify | ||||
| + *  it under the terms of the GNU General Public License version 2 as | ||||
| + *  publishhed by the Free Software Foundation. | ||||
| + * | ||||
| + *  Copyright (C) 2015 John Crispin <blogic@openwrt.org> | ||||
| + */ | ||||
| + | ||||
| +#include <linux/module.h> | ||||
| +#include <linux/platform_device.h> | ||||
| +#include <linux/of.h> | ||||
| +#include <linux/mtd/mtd.h> | ||||
| +#include <linux/gpio.h> | ||||
| + | ||||
| +#define LINKIT_LATCH_GPIO	11 | ||||
| + | ||||
| +struct linkit_hw_data { | ||||
| +	char board[16]; | ||||
| +	char rev[16]; | ||||
| +}; | ||||
| + | ||||
| +static void sanify_string(char *s) | ||||
| +{ | ||||
| +	int i; | ||||
| + | ||||
| +	for (i = 0; i < 15; i++) | ||||
| +		if (s[i] <= 0x20) | ||||
| +			s[i] = '\0'; | ||||
| +	s[15] = '\0'; | ||||
| +} | ||||
| + | ||||
| +static int linkit_probe(struct platform_device *pdev) | ||||
| +{ | ||||
| +	struct linkit_hw_data hw; | ||||
| +	struct mtd_info *mtd; | ||||
| +	size_t retlen; | ||||
| +	int ret; | ||||
| + | ||||
| +	mtd = get_mtd_device_nm("factory"); | ||||
| +	if (IS_ERR(mtd)) | ||||
| +		return PTR_ERR(mtd); | ||||
| + | ||||
| +	ret = mtd_read(mtd, 0x400, sizeof(hw), &retlen, (u_char *) &hw); | ||||
| +	put_mtd_device(mtd); | ||||
| + | ||||
| +	sanify_string(hw.board); | ||||
| +	sanify_string(hw.rev); | ||||
| + | ||||
| +	dev_info(&pdev->dev, "Version  : %s\n", hw.board); | ||||
| +	dev_info(&pdev->dev, "Revision : %s\n", hw.rev); | ||||
| + | ||||
| +	if (!strcmp(hw.board, "LINKITS7688")) { | ||||
| +		dev_info(&pdev->dev, "setting up bootstrap latch\n"); | ||||
| + | ||||
| +		if (devm_gpio_request(&pdev->dev, LINKIT_LATCH_GPIO, "bootstrap")) { | ||||
| +			dev_err(&pdev->dev, "failed to setup bootstrap gpio\n"); | ||||
| +			return -1; | ||||
| +		} | ||||
| +		gpio_direction_output(LINKIT_LATCH_GPIO, 0); | ||||
| +	} | ||||
| + | ||||
| +	return 0; | ||||
| +} | ||||
| + | ||||
| +static const struct of_device_id linkit_match[] = { | ||||
| +	{ .compatible = "mediatek,linkit" }, | ||||
| +	{}, | ||||
| +}; | ||||
| +MODULE_DEVICE_TABLE(of, linkit_match); | ||||
| + | ||||
| +static struct platform_driver linkit_driver = { | ||||
| +	.probe = linkit_probe, | ||||
| +	.driver = { | ||||
| +		.name = "mtk-linkit", | ||||
| +		.owner = THIS_MODULE, | ||||
| +		.of_match_table = linkit_match, | ||||
| +	}, | ||||
| +}; | ||||
| + | ||||
| +int __init linkit_init(void) | ||||
| +{ | ||||
| +	return platform_driver_register(&linkit_driver); | ||||
| +} | ||||
| +late_initcall_sync(linkit_init); | ||||
| @@ -0,0 +1,42 @@ | ||||
| --- a/arch/mips/include/asm/mach-ralink/mt7620.h | ||||
| +++ b/arch/mips/include/asm/mach-ralink/mt7620.h | ||||
| @@ -115,9 +115,14 @@ | ||||
|  #define MT7620_GPIO_MODE_WDT_MASK	0x3 | ||||
|  #define MT7620_GPIO_MODE_WDT_SHIFT	21 | ||||
|   | ||||
| +#define MT7620_GPIO_MODE_MDIO		0 | ||||
| +#define MT7620_GPIO_MODE_MDIO_REFCLK	1 | ||||
| +#define MT7620_GPIO_MODE_MDIO_GPIO	2 | ||||
| +#define MT7620_GPIO_MODE_MDIO_MASK	0x3 | ||||
| +#define MT7620_GPIO_MODE_MDIO_SHIFT	7 | ||||
| + | ||||
|  #define MT7620_GPIO_MODE_I2C		0 | ||||
|  #define MT7620_GPIO_MODE_UART1		5 | ||||
| -#define MT7620_GPIO_MODE_MDIO		8 | ||||
|  #define MT7620_GPIO_MODE_RGMII1		9 | ||||
|  #define MT7620_GPIO_MODE_RGMII2		10 | ||||
|  #define MT7620_GPIO_MODE_SPI		11 | ||||
| --- a/arch/mips/ralink/mt7620.c | ||||
| +++ b/arch/mips/ralink/mt7620.c | ||||
| @@ -55,7 +55,10 @@ static int dram_type; | ||||
|  static struct rt2880_pmx_func i2c_grp[] =  { FUNC("i2c", 0, 1, 2) }; | ||||
|  static struct rt2880_pmx_func spi_grp[] = { FUNC("spi", 0, 3, 4) }; | ||||
|  static struct rt2880_pmx_func uartlite_grp[] = { FUNC("uartlite", 0, 15, 2) }; | ||||
| -static struct rt2880_pmx_func mdio_grp[] = { FUNC("mdio", 0, 22, 2) }; | ||||
| +static struct rt2880_pmx_func mdio_grp[] = { | ||||
| +	FUNC("mdio", MT7620_GPIO_MODE_MDIO, 22, 2), | ||||
| +	FUNC("refclk", MT7620_GPIO_MODE_MDIO_REFCLK, 22, 2), | ||||
| +}; | ||||
|  static struct rt2880_pmx_func rgmii1_grp[] = { FUNC("rgmii1", 0, 24, 12) }; | ||||
|  static struct rt2880_pmx_func refclk_grp[] = { FUNC("spi refclk", 0, 37, 3) }; | ||||
|  static struct rt2880_pmx_func ephy_grp[] = { FUNC("ephy", 0, 40, 5) }; | ||||
| @@ -92,7 +95,8 @@ static struct rt2880_pmx_group mt7620a_p | ||||
|  	GRP("uartlite", uartlite_grp, 1, MT7620_GPIO_MODE_UART1), | ||||
|  	GRP_G("wdt", wdt_grp, MT7620_GPIO_MODE_WDT_MASK, | ||||
|  		MT7620_GPIO_MODE_WDT_GPIO, MT7620_GPIO_MODE_WDT_SHIFT), | ||||
| -	GRP("mdio", mdio_grp, 1, MT7620_GPIO_MODE_MDIO), | ||||
| +	GRP_G("mdio", mdio_grp, MT7620_GPIO_MODE_MDIO_MASK, | ||||
| +		MT7620_GPIO_MODE_MDIO_GPIO, MT7620_GPIO_MODE_MDIO_SHIFT), | ||||
|  	GRP("rgmii1", rgmii1_grp, 1, MT7620_GPIO_MODE_RGMII1), | ||||
|  	GRP("spi refclk", refclk_grp, 1, MT7620_GPIO_MODE_SPI_REF_CLK), | ||||
|  	GRP_G("pcie", pcie_rst_grp, MT7620_GPIO_MODE_PCIE_MASK, | ||||
| @@ -0,0 +1,67 @@ | ||||
| --- a/arch/mips/ralink/mt7620.c | ||||
| +++ b/arch/mips/ralink/mt7620.c | ||||
| @@ -513,6 +513,7 @@ void __init ralink_clk_init(void) | ||||
|  	unsigned long sys_rate; | ||||
|  	unsigned long dram_rate; | ||||
|  	unsigned long periph_rate; | ||||
| +	unsigned long pcmi2s_rate; | ||||
|   | ||||
|  	xtal_rate = mt7620_get_xtal_rate(); | ||||
|   | ||||
| @@ -527,6 +528,7 @@ void __init ralink_clk_init(void) | ||||
|  			cpu_rate = MHZ(575); | ||||
|  		dram_rate = sys_rate = cpu_rate / 3; | ||||
|  		periph_rate = MHZ(40); | ||||
| +		pcmi2s_rate = MHZ(480); | ||||
|   | ||||
|  		ralink_clk_add("10000d00.uartlite", periph_rate); | ||||
|  		ralink_clk_add("10000e00.uartlite", periph_rate); | ||||
| @@ -538,6 +540,7 @@ void __init ralink_clk_init(void) | ||||
|  		dram_rate = mt7620_get_dram_rate(pll_rate); | ||||
|  		sys_rate = mt7620_get_sys_rate(cpu_rate); | ||||
|  		periph_rate = mt7620_get_periph_rate(xtal_rate); | ||||
| +		pcmi2s_rate = periph_rate; | ||||
|   | ||||
|  		pr_debug(RFMT("XTAL") RFMT("CPU_PLL") RFMT("PLL"), | ||||
|  			 RINT(xtal_rate), RFRAC(xtal_rate), | ||||
| @@ -559,6 +562,8 @@ void __init ralink_clk_init(void) | ||||
|  	ralink_clk_add("cpu", cpu_rate); | ||||
|  	ralink_clk_add("10000100.timer", periph_rate); | ||||
|  	ralink_clk_add("10000120.watchdog", periph_rate); | ||||
| +	ralink_clk_add("10000900.i2c", periph_rate); | ||||
| +	ralink_clk_add("10000a00.i2s", pcmi2s_rate); | ||||
|  	ralink_clk_add("10000b00.spi", sys_rate); | ||||
|  	ralink_clk_add("10000b40.spi", sys_rate); | ||||
|  	ralink_clk_add("10000c00.uartlite", periph_rate); | ||||
| --- a/arch/mips/ralink/rt288x.c | ||||
| +++ b/arch/mips/ralink/rt288x.c | ||||
| @@ -75,6 +75,7 @@ void __init ralink_clk_init(void) | ||||
|  	ralink_clk_add("300100.timer", cpu_rate / 2); | ||||
|  	ralink_clk_add("300120.watchdog", cpu_rate / 2); | ||||
|  	ralink_clk_add("300500.uart", cpu_rate / 2); | ||||
| +	ralink_clk_add("300900.i2c", cpu_rate / 2); | ||||
|  	ralink_clk_add("300c00.uartlite", cpu_rate / 2); | ||||
|  	ralink_clk_add("400000.ethernet", cpu_rate / 2); | ||||
|  	ralink_clk_add("480000.wmac", wmac_rate); | ||||
| --- a/arch/mips/ralink/rt305x.c | ||||
| +++ b/arch/mips/ralink/rt305x.c | ||||
| @@ -200,6 +200,8 @@ void __init ralink_clk_init(void) | ||||
|   | ||||
|  	ralink_clk_add("cpu", cpu_rate); | ||||
|  	ralink_clk_add("sys", sys_rate); | ||||
| +	ralink_clk_add("10000900.i2c", uart_rate); | ||||
| +	ralink_clk_add("10000a00.i2s", uart_rate); | ||||
|  	ralink_clk_add("10000b00.spi", sys_rate); | ||||
|  	ralink_clk_add("10000b40.spi", sys_rate); | ||||
|  	ralink_clk_add("10000100.timer", wdt_rate); | ||||
| --- a/arch/mips/ralink/rt3883.c | ||||
| +++ b/arch/mips/ralink/rt3883.c | ||||
| @@ -108,6 +108,8 @@ void __init ralink_clk_init(void) | ||||
|  	ralink_clk_add("10000100.timer", sys_rate); | ||||
|  	ralink_clk_add("10000120.watchdog", sys_rate); | ||||
|  	ralink_clk_add("10000500.uart", 40000000); | ||||
| +	ralink_clk_add("10000900.i2c", 40000000); | ||||
| +	ralink_clk_add("10000a00.i2s", 40000000); | ||||
|  	ralink_clk_add("10000b00.spi", sys_rate); | ||||
|  	ralink_clk_add("10000b40.spi", sys_rate); | ||||
|  	ralink_clk_add("10000c00.uartlite", 40000000); | ||||
| @@ -0,0 +1,43 @@ | ||||
| From 8b61a1a33e41456ebeafa0ebe7ec0fccf859861e Mon Sep 17 00:00:00 2001 | ||||
| From: Nikolay Martynov <mar.kolya@gmail.com> | ||||
| Date: Wed, 25 Nov 2015 20:43:46 -0500 | ||||
| Subject: [PATCH] mtd: nand: Fix Spansion sparearea size detection | ||||
|  | ||||
| According to datasheet S34ML02G2 and S34ML04G2 have | ||||
| larger sparea area size than was detected. | ||||
|  | ||||
| Signed-off-by: Nikolay Martynov <mar.kolya@gmail.com> | ||||
| --- | ||||
|  drivers/mtd/nand/nand_base.c | 9 +++++++++ | ||||
|  1 file changed, 9 insertions(+) | ||||
|  | ||||
| --- a/drivers/mtd/nand/nand_base.c | ||||
| +++ b/drivers/mtd/nand/nand_base.c | ||||
| @@ -3767,6 +3767,7 @@ static void nand_decode_ext_id(struct mt | ||||
|  	/* | ||||
|  	 * Field definitions are in the following datasheets: | ||||
|  	 * Old style (4,5 byte ID): Samsung K9GAG08U0M (p.32) | ||||
| +	 *                          Spansion S34ML02G2 (p.33) | ||||
|  	 * New Samsung (6 byte ID): Samsung K9GAG08U0F (p.44) | ||||
|  	 * Hynix MLC   (6 byte ID): Hynix H27UBG8T2B (p.22) | ||||
|  	 * | ||||
| @@ -3864,6 +3865,19 @@ static void nand_decode_ext_id(struct mt | ||||
|  		*busw = (extid & 0x01) ? NAND_BUSWIDTH_16 : 0; | ||||
|   | ||||
|  		/* | ||||
| +		 * Spansion S34ML0[24]G2 have oobsize twice as large | ||||
| +		 * as S34ML01G2 encoded in the same bit. We | ||||
| +		 * differinciate them by their ID length | ||||
| +		 */ | ||||
| +		if (id_data[0] == NAND_MFR_AMD | ||||
| +		    		&& (id_data[1] == 0xda | ||||
| +				 || id_data[1] == 0xdc | ||||
| +				 || id_data[1] == 0xca | ||||
| +				 || id_data[1] == 0xcc)) { | ||||
| +			mtd->oobsize *= 2; | ||||
| +		} | ||||
| + | ||||
| +		/* | ||||
|  		 * Toshiba 24nm raw SLC (i.e., not BENAND) have 32B OOB per | ||||
|  		 * 512B page. For Toshiba SLC, we decode the 5th/6th byte as | ||||
|  		 * follows: | ||||
| @@ -0,0 +1,61 @@ | ||||
| There is a variant of MT7621 which contains only one CPU core instead of 2. | ||||
| This is not reflected in the config register, so the kernel detects more | ||||
| physical cores, which leads to a hang on SMP bringup. | ||||
| Add a hack to detect missing cores. | ||||
|  | ||||
| Signed-off-by: Felix Fietkau <nbd@nbd.name> | ||||
|  | ||||
| --- a/arch/mips/kernel/smp-cps.c | ||||
| +++ b/arch/mips/kernel/smp-cps.c | ||||
| @@ -56,6 +56,11 @@ static unsigned core_vpe_count(unsigned | ||||
|  	return (cfg >> CM_GCR_Cx_CONFIG_PVPE_SHF) + 1; | ||||
|  } | ||||
|   | ||||
| +bool __weak plat_cpu_core_present(int core) | ||||
| +{ | ||||
| +	return true; | ||||
| +} | ||||
| + | ||||
|  static void __init cps_smp_setup(void) | ||||
|  { | ||||
|  	unsigned int ncores, nvpes, core_vpes; | ||||
| @@ -66,6 +71,8 @@ static void __init cps_smp_setup(void) | ||||
|  	ncores = mips_cm_numcores(); | ||||
|  	pr_info("%s topology ", cpu_has_mips_r6 ? "VP" : "VPE"); | ||||
|  	for (c = nvpes = 0; c < ncores; c++) { | ||||
| +		if (!plat_cpu_core_present(c)) | ||||
| +			continue; | ||||
|  		core_vpes = core_vpe_count(c); | ||||
|  		pr_cont("%c%u", c ? ',' : '{', core_vpes); | ||||
|   | ||||
| --- a/arch/mips/ralink/mt7621.c | ||||
| +++ b/arch/mips/ralink/mt7621.c | ||||
| @@ -17,6 +17,7 @@ | ||||
|  #include <asm/mips-cpc.h> | ||||
|  #include <asm/mach-ralink/ralink_regs.h> | ||||
|  #include <asm/mach-ralink/mt7621.h> | ||||
| +#include <asm/mips-boards/launch.h> | ||||
|   | ||||
|  #include <pinmux.h> | ||||
|   | ||||
| @@ -164,6 +165,20 @@ void __init ralink_of_remap(void) | ||||
|  		panic("Failed to remap core resources"); | ||||
|  } | ||||
|   | ||||
| +bool plat_cpu_core_present(int core) | ||||
| +{ | ||||
| +	struct cpulaunch *launch = (struct cpulaunch *)CKSEG0ADDR(CPULAUNCH); | ||||
| + | ||||
| +	if (!core) | ||||
| +		return true; | ||||
| +	launch += core * 2; /* 2 VPEs per core */ | ||||
| +	if (!(launch->flags & LAUNCH_FREADY)) | ||||
| +		return false; | ||||
| +	if (launch->flags & (LAUNCH_FGO | LAUNCH_FGONE)) | ||||
| +		return false; | ||||
| +	return true; | ||||
| +} | ||||
| + | ||||
|  void prom_soc_init(struct ralink_soc_info *soc_info) | ||||
|  { | ||||
|  	void __iomem *sysc = (void __iomem *) KSEG1ADDR(MT7621_SYSC_BASE); | ||||
| @@ -0,0 +1,21 @@ | ||||
| From 2583143af8111d430bdca0268b6cdb7ccc7c3f9d Mon Sep 17 00:00:00 2001 | ||||
| From: Daniel Golle <daniel@makrotopia.org> | ||||
| Date: Fri, 13 Jan 2017 05:40:04 +0100 | ||||
| Subject: [PATCH] mips: ralink/rt3883: fix typo in pinctrl lna_g_func | ||||
|  | ||||
| Signed-off-by: Daniel Golle <daniel@makrotopia.org> | ||||
| --- | ||||
|  arch/mips/ralink/rt3883.c | 2 +- | ||||
|  1 file changed, 1 insertion(+), 1 deletion(-) | ||||
|  | ||||
| --- a/arch/mips/ralink/rt3883.c | ||||
| +++ b/arch/mips/ralink/rt3883.c | ||||
| @@ -36,7 +36,7 @@ static struct rt2880_pmx_func uartlite_f | ||||
|  static struct rt2880_pmx_func jtag_func[] = { FUNC("jtag", 0, 17, 5) }; | ||||
|  static struct rt2880_pmx_func mdio_func[] = { FUNC("mdio", 0, 22, 2) }; | ||||
|  static struct rt2880_pmx_func lna_a_func[] = { FUNC("lna a", 0, 32, 3) }; | ||||
| -static struct rt2880_pmx_func lna_g_func[] = { FUNC("lna a", 0, 35, 3) }; | ||||
| +static struct rt2880_pmx_func lna_g_func[] = { FUNC("lna g", 0, 35, 3) }; | ||||
|  static struct rt2880_pmx_func pci_func[] = { | ||||
|  	FUNC("pci-dev", 0, 40, 32), | ||||
|  	FUNC("pci-host2", 1, 40, 32), | ||||
							
								
								
									
										26
									
								
								target/linux/ramips/patches-4.9/301-fix-rt3883.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								target/linux/ramips/patches-4.9/301-fix-rt3883.patch
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| --- a/arch/mips/ralink/rt3883.c | ||||
| +++ b/arch/mips/ralink/rt3883.c | ||||
| @@ -63,16 +63,6 @@ | ||||
|  	{ 0 } | ||||
|  }; | ||||
|   | ||||
| -static void rt3883_wdt_reset(void) | ||||
| -{ | ||||
| -	u32 t; | ||||
| - | ||||
| -	/* enable WDT reset output on GPIO 2 */ | ||||
| -	t = rt_sysc_r32(RT3883_SYSC_REG_SYSCFG1); | ||||
| -	t |= RT3883_SYSCFG1_GPIO2_AS_WDT_OUT; | ||||
| -	rt_sysc_w32(t, RT3883_SYSC_REG_SYSCFG1); | ||||
| -} | ||||
| - | ||||
|  void __init ralink_clk_init(void) | ||||
|  { | ||||
|  	unsigned long cpu_rate, sys_rate; | ||||
| @@ -157,5 +147,5 @@ | ||||
|   | ||||
|  	rt2880_pinmux_data = rt3883_pinmux_data; | ||||
|   | ||||
| -	ralink_soc == RT3883_SOC; | ||||
| +	ralink_soc = RT3883_SOC; | ||||
|  } | ||||
							
								
								
									
										211
									
								
								target/linux/ramips/rt288x/config-4.9
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										211
									
								
								target/linux/ramips/rt288x/config-4.9
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,211 @@ | ||||
| CONFIG_ARCH_BINFMT_ELF_STATE=y | ||||
| CONFIG_ARCH_CLOCKSOURCE_DATA=y | ||||
| CONFIG_ARCH_DISCARD_MEMBLOCK=y | ||||
| CONFIG_ARCH_HAS_ELF_RANDOMIZE=y | ||||
| # CONFIG_ARCH_HAS_GCOV_PROFILE_ALL is not set | ||||
| CONFIG_ARCH_HAS_RESET_CONTROLLER=y | ||||
| # CONFIG_ARCH_HAS_SG_CHAIN is not set | ||||
| CONFIG_ARCH_HIBERNATION_POSSIBLE=y | ||||
| CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y | ||||
| CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y | ||||
| CONFIG_ARCH_SUPPORTS_UPROBES=y | ||||
| CONFIG_ARCH_SUSPEND_POSSIBLE=y | ||||
| CONFIG_ARCH_USE_BUILTIN_BSWAP=y | ||||
| CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y | ||||
| CONFIG_BLK_MQ_PCI=y | ||||
| CONFIG_CEVT_R4K=y | ||||
| # CONFIG_CEVT_SYSTICK_QUIRK is not set | ||||
| CONFIG_CLKDEV_LOOKUP=y | ||||
| CONFIG_CLONE_BACKWARDS=y | ||||
| CONFIG_CMDLINE="rootfstype=squashfs,jffs2" | ||||
| CONFIG_CMDLINE_BOOL=y | ||||
| # CONFIG_CMDLINE_OVERRIDE is not set | ||||
| CONFIG_CPU_GENERIC_DUMP_TLB=y | ||||
| CONFIG_CPU_HAS_PREFETCH=y | ||||
| CONFIG_CPU_HAS_RIXI=y | ||||
| CONFIG_CPU_HAS_SYNC=y | ||||
| CONFIG_CPU_LITTLE_ENDIAN=y | ||||
| CONFIG_CPU_MIPS32=y | ||||
| # CONFIG_CPU_MIPS32_R1 is not set | ||||
| CONFIG_CPU_MIPS32_R2=y | ||||
| CONFIG_CPU_MIPSR2=y | ||||
| CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y | ||||
| CONFIG_CPU_R4K_CACHE_TLB=y | ||||
| CONFIG_CPU_R4K_FPU=y | ||||
| CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y | ||||
| CONFIG_CPU_SUPPORTS_HIGHMEM=y | ||||
| CONFIG_CPU_SUPPORTS_MSA=y | ||||
| CONFIG_CRYPTO_RNG2=y | ||||
| CONFIG_CRYPTO_WORKQUEUE=y | ||||
| CONFIG_CSRC_R4K=y | ||||
| CONFIG_DMA_NONCOHERENT=y | ||||
| # CONFIG_DTB_RT2880_EVAL is not set | ||||
| CONFIG_DTB_RT_NONE=y | ||||
| CONFIG_DTC=y | ||||
| CONFIG_EARLY_PRINTK=y | ||||
| CONFIG_FIXED_PHY=y | ||||
| CONFIG_GENERIC_ATOMIC64=y | ||||
| CONFIG_GENERIC_CLOCKEVENTS=y | ||||
| CONFIG_GENERIC_CMOS_UPDATE=y | ||||
| CONFIG_GENERIC_IO=y | ||||
| CONFIG_GENERIC_IRQ_CHIP=y | ||||
| CONFIG_GENERIC_IRQ_SHOW=y | ||||
| CONFIG_GENERIC_PCI_IOMAP=y | ||||
| CONFIG_GENERIC_SCHED_CLOCK=y | ||||
| CONFIG_GENERIC_SMP_IDLE_THREAD=y | ||||
| CONFIG_GENERIC_TIME_VSYSCALL=y | ||||
| CONFIG_GPIOLIB=y | ||||
| CONFIG_GPIO_RALINK=y | ||||
| CONFIG_GPIO_SYSFS=y | ||||
| CONFIG_HANDLE_DOMAIN_IRQ=y | ||||
| CONFIG_HARDWARE_WATCHPOINTS=y | ||||
| CONFIG_HAS_DMA=y | ||||
| CONFIG_HAS_IOMEM=y | ||||
| CONFIG_HAS_IOPORT_MAP=y | ||||
| # CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set | ||||
| # CONFIG_HAVE_ARCH_BITREVERSE is not set | ||||
| CONFIG_HAVE_ARCH_JUMP_LABEL=y | ||||
| CONFIG_HAVE_ARCH_KGDB=y | ||||
| CONFIG_HAVE_ARCH_SECCOMP_FILTER=y | ||||
| CONFIG_HAVE_ARCH_TRACEHOOK=y | ||||
| # CONFIG_HAVE_BOOTMEM_INFO_NODE is not set | ||||
| CONFIG_HAVE_CBPF_JIT=y | ||||
| CONFIG_HAVE_CC_STACKPROTECTOR=y | ||||
| CONFIG_HAVE_CLK=y | ||||
| CONFIG_HAVE_CONTEXT_TRACKING=y | ||||
| CONFIG_HAVE_C_RECORDMCOUNT=y | ||||
| CONFIG_HAVE_DEBUG_KMEMLEAK=y | ||||
| CONFIG_HAVE_DEBUG_STACKOVERFLOW=y | ||||
| CONFIG_HAVE_DMA_API_DEBUG=y | ||||
| CONFIG_HAVE_DMA_CONTIGUOUS=y | ||||
| CONFIG_HAVE_DYNAMIC_FTRACE=y | ||||
| CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y | ||||
| CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y | ||||
| CONFIG_HAVE_FUNCTION_TRACER=y | ||||
| CONFIG_HAVE_GENERIC_DMA_COHERENT=y | ||||
| CONFIG_HAVE_IDE=y | ||||
| CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y | ||||
| CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y | ||||
| CONFIG_HAVE_KVM=y | ||||
| CONFIG_HAVE_LATENCYTOP_SUPPORT=y | ||||
| CONFIG_HAVE_MEMBLOCK=y | ||||
| CONFIG_HAVE_MEMBLOCK_NODE_MAP=y | ||||
| CONFIG_HAVE_MOD_ARCH_SPECIFIC=y | ||||
| CONFIG_HAVE_NET_DSA=y | ||||
| CONFIG_HAVE_OPROFILE=y | ||||
| CONFIG_HAVE_PERF_EVENTS=y | ||||
| CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y | ||||
| CONFIG_HAVE_SYSCALL_TRACEPOINTS=y | ||||
| CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y | ||||
| CONFIG_HW_HAS_PCI=y | ||||
| CONFIG_HZ_PERIODIC=y | ||||
| CONFIG_INITRAMFS_SOURCE="" | ||||
| CONFIG_IP17XX_PHY=y | ||||
| CONFIG_IRQCHIP=y | ||||
| CONFIG_IRQ_DOMAIN=y | ||||
| CONFIG_IRQ_FORCED_THREADING=y | ||||
| CONFIG_IRQ_INTC=y | ||||
| CONFIG_IRQ_MIPS_CPU=y | ||||
| CONFIG_IRQ_WORK=y | ||||
| CONFIG_LIBFDT=y | ||||
| CONFIG_MDIO_BOARDINFO=y | ||||
| CONFIG_MIPS=y | ||||
| CONFIG_MIPS_ASID_BITS=8 | ||||
| CONFIG_MIPS_ASID_SHIFT=0 | ||||
| CONFIG_MIPS_CLOCK_VSYSCALL=y | ||||
| # CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND is not set | ||||
| # CONFIG_MIPS_CMDLINE_DTB_EXTEND is not set | ||||
| # CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set | ||||
| CONFIG_MIPS_CMDLINE_FROM_DTB=y | ||||
| # CONFIG_MIPS_ELF_APPENDED_DTB is not set | ||||
| # CONFIG_MIPS_HUGE_TLB_SUPPORT is not set | ||||
| CONFIG_MIPS_L1_CACHE_SHIFT=4 | ||||
| CONFIG_MIPS_L1_CACHE_SHIFT_4=y | ||||
| # CONFIG_MIPS_MACHINE is not set | ||||
| # CONFIG_MIPS_NO_APPENDED_DTB is not set | ||||
| CONFIG_MIPS_RAW_APPENDED_DTB=y | ||||
| CONFIG_MIPS_SPRAM=y | ||||
| CONFIG_MODULES_USE_ELF_REL=y | ||||
| # CONFIG_MTD_CFI_INTELEXT is not set | ||||
| CONFIG_MTD_CMDLINE_PARTS=y | ||||
| CONFIG_MTD_M25P80=y | ||||
| CONFIG_MTD_PHYSMAP=y | ||||
| CONFIG_MTD_SPI_NOR=y | ||||
| CONFIG_MTD_SPLIT_FIRMWARE=y | ||||
| CONFIG_MTD_SPLIT_LZMA_FW=y | ||||
| CONFIG_MTD_SPLIT_UIMAGE_FW=y | ||||
| CONFIG_NEED_DMA_MAP_STATE=y | ||||
| CONFIG_NEED_PER_CPU_KM=y | ||||
| CONFIG_NET_MEDIATEK_MDIO=y | ||||
| CONFIG_NET_MEDIATEK_MDIO_RT2880=y | ||||
| CONFIG_NET_MEDIATEK_RT2880=y | ||||
| CONFIG_NET_MEDIATEK_SOC=y | ||||
| CONFIG_NET_VENDOR_MEDIATEK=y | ||||
| CONFIG_NLS=m | ||||
| CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y | ||||
| # CONFIG_NO_IOPORT_MAP is not set | ||||
| CONFIG_OF=y | ||||
| CONFIG_OF_ADDRESS=y | ||||
| CONFIG_OF_ADDRESS_PCI=y | ||||
| CONFIG_OF_EARLY_FLATTREE=y | ||||
| CONFIG_OF_FLATTREE=y | ||||
| CONFIG_OF_GPIO=y | ||||
| CONFIG_OF_IRQ=y | ||||
| CONFIG_OF_MDIO=y | ||||
| CONFIG_OF_NET=y | ||||
| CONFIG_OF_PCI=y | ||||
| CONFIG_OF_PCI_IRQ=y | ||||
| CONFIG_PCI=y | ||||
| CONFIG_PCI_DOMAINS=y | ||||
| CONFIG_PCI_DRIVERS_LEGACY=y | ||||
| CONFIG_PERF_USE_VMALLOC=y | ||||
| CONFIG_PGTABLE_LEVELS=2 | ||||
| CONFIG_PHYLIB=y | ||||
| # CONFIG_PHY_RALINK_USB is not set | ||||
| CONFIG_PINCTRL=y | ||||
| CONFIG_PINCTRL_RT2880=y | ||||
| # CONFIG_PINCTRL_SINGLE is not set | ||||
| CONFIG_RALINK=y | ||||
| CONFIG_RALINK_WDT=y | ||||
| # CONFIG_RCU_STALL_COMMON is not set | ||||
| CONFIG_RESET_CONTROLLER=y | ||||
| CONFIG_SCHED_HRTICK=y | ||||
| # CONFIG_SCHED_INFO is not set | ||||
| # CONFIG_SCSI_DMA is not set | ||||
| # CONFIG_SERIAL_8250_FSL is not set | ||||
| CONFIG_SERIAL_8250_RT288X=y | ||||
| CONFIG_SERIAL_OF_PLATFORM=y | ||||
| # CONFIG_SG_POOL is not set | ||||
| # CONFIG_SOC_MT7620 is not set | ||||
| # CONFIG_SOC_MT7621 is not set | ||||
| CONFIG_SOC_RT288X=y | ||||
| # CONFIG_SOC_RT305X is not set | ||||
| # CONFIG_SOC_RT3883 is not set | ||||
| CONFIG_SPI=y | ||||
| CONFIG_SPI_MASTER=y | ||||
| # CONFIG_SPI_MT7621 is not set | ||||
| CONFIG_SPI_RT2880=y | ||||
| CONFIG_SRCU=y | ||||
| CONFIG_SWCONFIG=y | ||||
| CONFIG_SWPHY=y | ||||
| CONFIG_SYSCTL_EXCEPTION_TRACE=y | ||||
| CONFIG_SYS_HAS_CPU_MIPS32_R1=y | ||||
| CONFIG_SYS_HAS_CPU_MIPS32_R2=y | ||||
| CONFIG_SYS_HAS_EARLY_PRINTK=y | ||||
| CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y | ||||
| CONFIG_SYS_SUPPORTS_ARBIT_HZ=y | ||||
| CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y | ||||
| CONFIG_SYS_SUPPORTS_MIPS16=y | ||||
| CONFIG_TICK_CPU_ACCOUNTING=y | ||||
| CONFIG_USB=m | ||||
| CONFIG_USB_COMMON=m | ||||
| CONFIG_USB_EHCI_HCD=m | ||||
| CONFIG_USB_EHCI_HCD_PLATFORM=m | ||||
| CONFIG_USB_EHCI_PCI=m | ||||
| CONFIG_USB_OHCI_HCD=m | ||||
| CONFIG_USB_OHCI_HCD_PCI=m | ||||
| CONFIG_USB_OHCI_HCD_PLATFORM=m | ||||
| CONFIG_USB_SUPPORT=y | ||||
| # CONFIG_USB_UHCI_HCD is not set | ||||
| CONFIG_USE_OF=y | ||||
| CONFIG_WATCHDOG_CORE=y | ||||
							
								
								
									
										199
									
								
								target/linux/ramips/rt305x/config-4.9
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								target/linux/ramips/rt305x/config-4.9
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,199 @@ | ||||
| CONFIG_ARCH_BINFMT_ELF_STATE=y | ||||
| CONFIG_ARCH_CLOCKSOURCE_DATA=y | ||||
| CONFIG_ARCH_DISCARD_MEMBLOCK=y | ||||
| CONFIG_ARCH_HAS_ELF_RANDOMIZE=y | ||||
| # CONFIG_ARCH_HAS_GCOV_PROFILE_ALL is not set | ||||
| CONFIG_ARCH_HAS_RESET_CONTROLLER=y | ||||
| # CONFIG_ARCH_HAS_SG_CHAIN is not set | ||||
| CONFIG_ARCH_HIBERNATION_POSSIBLE=y | ||||
| CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y | ||||
| CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y | ||||
| CONFIG_ARCH_SUPPORTS_UPROBES=y | ||||
| CONFIG_ARCH_SUSPEND_POSSIBLE=y | ||||
| CONFIG_ARCH_USE_BUILTIN_BSWAP=y | ||||
| CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y | ||||
| CONFIG_CEVT_R4K=y | ||||
| CONFIG_CEVT_SYSTICK_QUIRK=y | ||||
| CONFIG_CLKDEV_LOOKUP=y | ||||
| CONFIG_CLKEVT_RT3352=y | ||||
| CONFIG_CLKSRC_MMIO=y | ||||
| CONFIG_CLKSRC_OF=y | ||||
| CONFIG_CLKSRC_PROBE=y | ||||
| CONFIG_CLONE_BACKWARDS=y | ||||
| CONFIG_CMDLINE="rootfstype=squashfs,jffs2" | ||||
| CONFIG_CMDLINE_BOOL=y | ||||
| # CONFIG_CMDLINE_OVERRIDE is not set | ||||
| CONFIG_CPU_GENERIC_DUMP_TLB=y | ||||
| CONFIG_CPU_HAS_PREFETCH=y | ||||
| CONFIG_CPU_HAS_RIXI=y | ||||
| CONFIG_CPU_HAS_SYNC=y | ||||
| CONFIG_CPU_LITTLE_ENDIAN=y | ||||
| CONFIG_CPU_MIPS32=y | ||||
| # CONFIG_CPU_MIPS32_R1 is not set | ||||
| CONFIG_CPU_MIPS32_R2=y | ||||
| CONFIG_CPU_MIPSR2=y | ||||
| CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y | ||||
| CONFIG_CPU_R4K_CACHE_TLB=y | ||||
| CONFIG_CPU_R4K_FPU=y | ||||
| CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y | ||||
| CONFIG_CPU_SUPPORTS_HIGHMEM=y | ||||
| CONFIG_CPU_SUPPORTS_MSA=y | ||||
| CONFIG_CRYPTO_RNG2=y | ||||
| CONFIG_CRYPTO_WORKQUEUE=y | ||||
| CONFIG_CSRC_R4K=y | ||||
| CONFIG_DEBUG_PINCTRL=y | ||||
| CONFIG_DMA_NONCOHERENT=y | ||||
| # CONFIG_DTB_RT305X_EVAL is not set | ||||
| CONFIG_DTB_RT_NONE=y | ||||
| CONFIG_DTC=y | ||||
| CONFIG_EARLY_PRINTK=y | ||||
| CONFIG_FIXED_PHY=y | ||||
| CONFIG_GENERIC_ATOMIC64=y | ||||
| CONFIG_GENERIC_CLOCKEVENTS=y | ||||
| CONFIG_GENERIC_CMOS_UPDATE=y | ||||
| CONFIG_GENERIC_IO=y | ||||
| CONFIG_GENERIC_IRQ_CHIP=y | ||||
| CONFIG_GENERIC_IRQ_SHOW=y | ||||
| CONFIG_GENERIC_PCI_IOMAP=y | ||||
| CONFIG_GENERIC_PHY=y | ||||
| CONFIG_GENERIC_SCHED_CLOCK=y | ||||
| CONFIG_GENERIC_SMP_IDLE_THREAD=y | ||||
| CONFIG_GENERIC_TIME_VSYSCALL=y | ||||
| CONFIG_GPIOLIB=y | ||||
| CONFIG_GPIO_RALINK=y | ||||
| CONFIG_GPIO_SYSFS=y | ||||
| CONFIG_HANDLE_DOMAIN_IRQ=y | ||||
| CONFIG_HARDWARE_WATCHPOINTS=y | ||||
| CONFIG_HAS_DMA=y | ||||
| CONFIG_HAS_IOMEM=y | ||||
| CONFIG_HAS_IOPORT_MAP=y | ||||
| # CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set | ||||
| # CONFIG_HAVE_ARCH_BITREVERSE is not set | ||||
| CONFIG_HAVE_ARCH_JUMP_LABEL=y | ||||
| CONFIG_HAVE_ARCH_KGDB=y | ||||
| CONFIG_HAVE_ARCH_SECCOMP_FILTER=y | ||||
| CONFIG_HAVE_ARCH_TRACEHOOK=y | ||||
| # CONFIG_HAVE_BOOTMEM_INFO_NODE is not set | ||||
| CONFIG_HAVE_CBPF_JIT=y | ||||
| CONFIG_HAVE_CC_STACKPROTECTOR=y | ||||
| CONFIG_HAVE_CLK=y | ||||
| CONFIG_HAVE_CONTEXT_TRACKING=y | ||||
| CONFIG_HAVE_C_RECORDMCOUNT=y | ||||
| CONFIG_HAVE_DEBUG_KMEMLEAK=y | ||||
| CONFIG_HAVE_DEBUG_STACKOVERFLOW=y | ||||
| CONFIG_HAVE_DMA_API_DEBUG=y | ||||
| CONFIG_HAVE_DMA_CONTIGUOUS=y | ||||
| CONFIG_HAVE_DYNAMIC_FTRACE=y | ||||
| CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y | ||||
| CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y | ||||
| CONFIG_HAVE_FUNCTION_TRACER=y | ||||
| CONFIG_HAVE_GENERIC_DMA_COHERENT=y | ||||
| CONFIG_HAVE_IDE=y | ||||
| CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y | ||||
| CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y | ||||
| CONFIG_HAVE_KVM=y | ||||
| CONFIG_HAVE_LATENCYTOP_SUPPORT=y | ||||
| CONFIG_HAVE_MEMBLOCK=y | ||||
| CONFIG_HAVE_MEMBLOCK_NODE_MAP=y | ||||
| CONFIG_HAVE_MOD_ARCH_SPECIFIC=y | ||||
| CONFIG_HAVE_NET_DSA=y | ||||
| CONFIG_HAVE_OPROFILE=y | ||||
| CONFIG_HAVE_PERF_EVENTS=y | ||||
| CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y | ||||
| CONFIG_HAVE_SYSCALL_TRACEPOINTS=y | ||||
| CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y | ||||
| CONFIG_HZ_PERIODIC=y | ||||
| CONFIG_INITRAMFS_SOURCE="" | ||||
| CONFIG_IRQCHIP=y | ||||
| CONFIG_IRQ_DOMAIN=y | ||||
| CONFIG_IRQ_FORCED_THREADING=y | ||||
| CONFIG_IRQ_INTC=y | ||||
| CONFIG_IRQ_MIPS_CPU=y | ||||
| CONFIG_IRQ_WORK=y | ||||
| CONFIG_LIBFDT=y | ||||
| CONFIG_MDIO_BOARDINFO=y | ||||
| CONFIG_MIPS=y | ||||
| CONFIG_MIPS_ASID_BITS=8 | ||||
| CONFIG_MIPS_ASID_SHIFT=0 | ||||
| CONFIG_MIPS_CLOCK_VSYSCALL=y | ||||
| # CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND is not set | ||||
| # CONFIG_MIPS_CMDLINE_DTB_EXTEND is not set | ||||
| # CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set | ||||
| CONFIG_MIPS_CMDLINE_FROM_DTB=y | ||||
| # CONFIG_MIPS_ELF_APPENDED_DTB is not set | ||||
| # CONFIG_MIPS_HUGE_TLB_SUPPORT is not set | ||||
| CONFIG_MIPS_L1_CACHE_SHIFT=5 | ||||
| # CONFIG_MIPS_MACHINE is not set | ||||
| CONFIG_MIPS_NO_APPENDED_DTB=y | ||||
| # CONFIG_MIPS_RAW_APPENDED_DTB is not set | ||||
| CONFIG_MIPS_SPRAM=y | ||||
| CONFIG_MODULES_USE_ELF_REL=y | ||||
| # CONFIG_MTD_CFI_INTELEXT is not set | ||||
| CONFIG_MTD_CMDLINE_PARTS=y | ||||
| CONFIG_MTD_M25P80=y | ||||
| CONFIG_MTD_PHYSMAP=y | ||||
| CONFIG_MTD_SPI_NOR=y | ||||
| CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y | ||||
| CONFIG_MTD_SPLIT_FIRMWARE=y | ||||
| CONFIG_MTD_SPLIT_SEAMA_FW=y | ||||
| CONFIG_MTD_SPLIT_UIMAGE_FW=y | ||||
| CONFIG_NEED_DMA_MAP_STATE=y | ||||
| CONFIG_NEED_PER_CPU_KM=y | ||||
| CONFIG_NET_MEDIATEK_ESW_RT3050=y | ||||
| CONFIG_NET_MEDIATEK_RT3050=y | ||||
| CONFIG_NET_MEDIATEK_SOC=y | ||||
| CONFIG_NET_VENDOR_MEDIATEK=y | ||||
| CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y | ||||
| # CONFIG_NO_IOPORT_MAP is not set | ||||
| CONFIG_OF=y | ||||
| CONFIG_OF_ADDRESS=y | ||||
| CONFIG_OF_EARLY_FLATTREE=y | ||||
| CONFIG_OF_FLATTREE=y | ||||
| CONFIG_OF_GPIO=y | ||||
| CONFIG_OF_IRQ=y | ||||
| CONFIG_OF_MDIO=y | ||||
| CONFIG_OF_NET=y | ||||
| CONFIG_PCI_DRIVERS_LEGACY=y | ||||
| CONFIG_PERF_USE_VMALLOC=y | ||||
| CONFIG_PGTABLE_LEVELS=2 | ||||
| CONFIG_PHYLIB=y | ||||
| CONFIG_PHY_RALINK_USB=y | ||||
| CONFIG_PINCTRL=y | ||||
| CONFIG_PINCTRL_RT2880=y | ||||
| # CONFIG_PINCTRL_SINGLE is not set | ||||
| CONFIG_RALINK=y | ||||
| # CONFIG_RALINK_ILL_ACC is not set | ||||
| CONFIG_RALINK_WDT=y | ||||
| # CONFIG_RCU_STALL_COMMON is not set | ||||
| CONFIG_RESET_CONTROLLER=y | ||||
| CONFIG_SCHED_HRTICK=y | ||||
| # CONFIG_SCHED_INFO is not set | ||||
| # CONFIG_SCSI_DMA is not set | ||||
| # CONFIG_SERIAL_8250_FSL is not set | ||||
| CONFIG_SERIAL_8250_RT288X=y | ||||
| CONFIG_SERIAL_OF_PLATFORM=y | ||||
| # CONFIG_SG_POOL is not set | ||||
| # CONFIG_SOC_MT7620 is not set | ||||
| # CONFIG_SOC_MT7621 is not set | ||||
| # CONFIG_SOC_RT288X is not set | ||||
| CONFIG_SOC_RT305X=y | ||||
| # CONFIG_SOC_RT3883 is not set | ||||
| CONFIG_SPI=y | ||||
| CONFIG_SPI_MASTER=y | ||||
| # CONFIG_SPI_MT7621 is not set | ||||
| CONFIG_SPI_RT2880=y | ||||
| CONFIG_SRCU=y | ||||
| CONFIG_SWCONFIG=y | ||||
| CONFIG_SWPHY=y | ||||
| CONFIG_SYSCTL_EXCEPTION_TRACE=y | ||||
| CONFIG_SYS_HAS_CPU_MIPS32_R1=y | ||||
| CONFIG_SYS_HAS_CPU_MIPS32_R2=y | ||||
| CONFIG_SYS_HAS_EARLY_PRINTK=y | ||||
| CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y | ||||
| CONFIG_SYS_SUPPORTS_ARBIT_HZ=y | ||||
| CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y | ||||
| CONFIG_SYS_SUPPORTS_MIPS16=y | ||||
| CONFIG_TICK_CPU_ACCOUNTING=y | ||||
| CONFIG_USB_SUPPORT=y | ||||
| CONFIG_USE_OF=y | ||||
| CONFIG_WATCHDOG_CORE=y | ||||
							
								
								
									
										207
									
								
								target/linux/ramips/rt3883/config-4.9
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										207
									
								
								target/linux/ramips/rt3883/config-4.9
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,207 @@ | ||||
| CONFIG_AR8216_PHY=y | ||||
| CONFIG_ARCH_BINFMT_ELF_STATE=y | ||||
| CONFIG_ARCH_CLOCKSOURCE_DATA=y | ||||
| CONFIG_ARCH_DISCARD_MEMBLOCK=y | ||||
| CONFIG_ARCH_HAS_ELF_RANDOMIZE=y | ||||
| # CONFIG_ARCH_HAS_GCOV_PROFILE_ALL is not set | ||||
| CONFIG_ARCH_HAS_RESET_CONTROLLER=y | ||||
| # CONFIG_ARCH_HAS_SG_CHAIN is not set | ||||
| CONFIG_ARCH_HIBERNATION_POSSIBLE=y | ||||
| CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y | ||||
| CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y | ||||
| CONFIG_ARCH_SUPPORTS_UPROBES=y | ||||
| CONFIG_ARCH_SUSPEND_POSSIBLE=y | ||||
| CONFIG_ARCH_USE_BUILTIN_BSWAP=y | ||||
| CONFIG_ARCH_WANT_IPC_PARSE_VERSION=y | ||||
| CONFIG_BLK_MQ_PCI=y | ||||
| CONFIG_CEVT_R4K=y | ||||
| # CONFIG_CEVT_SYSTICK_QUIRK is not set | ||||
| CONFIG_CLKDEV_LOOKUP=y | ||||
| CONFIG_CLONE_BACKWARDS=y | ||||
| CONFIG_CMDLINE="rootfstype=squashfs,jffs2" | ||||
| CONFIG_CMDLINE_BOOL=y | ||||
| # CONFIG_CMDLINE_OVERRIDE is not set | ||||
| CONFIG_CPU_GENERIC_DUMP_TLB=y | ||||
| CONFIG_CPU_HAS_PREFETCH=y | ||||
| CONFIG_CPU_HAS_RIXI=y | ||||
| CONFIG_CPU_HAS_SYNC=y | ||||
| CONFIG_CPU_LITTLE_ENDIAN=y | ||||
| CONFIG_CPU_MIPS32=y | ||||
| # CONFIG_CPU_MIPS32_R1 is not set | ||||
| CONFIG_CPU_MIPS32_R2=y | ||||
| CONFIG_CPU_MIPSR2=y | ||||
| CONFIG_CPU_NEEDS_NO_SMARTMIPS_OR_MICROMIPS=y | ||||
| CONFIG_CPU_R4K_CACHE_TLB=y | ||||
| CONFIG_CPU_R4K_FPU=y | ||||
| CONFIG_CPU_SUPPORTS_32BIT_KERNEL=y | ||||
| CONFIG_CPU_SUPPORTS_HIGHMEM=y | ||||
| CONFIG_CPU_SUPPORTS_MSA=y | ||||
| CONFIG_CRYPTO_RNG2=y | ||||
| CONFIG_CRYPTO_WORKQUEUE=y | ||||
| CONFIG_CSRC_R4K=y | ||||
| CONFIG_DEBUG_PINCTRL=y | ||||
| CONFIG_DMA_NONCOHERENT=y | ||||
| # CONFIG_DTB_RT3883_EVAL is not set | ||||
| CONFIG_DTB_RT_NONE=y | ||||
| CONFIG_DTC=y | ||||
| CONFIG_EARLY_PRINTK=y | ||||
| CONFIG_ETHERNET_PACKET_MANGLE=y | ||||
| CONFIG_FIXED_PHY=y | ||||
| CONFIG_GENERIC_ATOMIC64=y | ||||
| CONFIG_GENERIC_CLOCKEVENTS=y | ||||
| CONFIG_GENERIC_CMOS_UPDATE=y | ||||
| CONFIG_GENERIC_IO=y | ||||
| CONFIG_GENERIC_IRQ_CHIP=y | ||||
| CONFIG_GENERIC_IRQ_SHOW=y | ||||
| CONFIG_GENERIC_PCI_IOMAP=y | ||||
| CONFIG_GENERIC_PHY=y | ||||
| CONFIG_GENERIC_SCHED_CLOCK=y | ||||
| CONFIG_GENERIC_SMP_IDLE_THREAD=y | ||||
| CONFIG_GENERIC_TIME_VSYSCALL=y | ||||
| CONFIG_GPIOLIB=y | ||||
| CONFIG_GPIO_RALINK=y | ||||
| CONFIG_GPIO_SYSFS=y | ||||
| CONFIG_HANDLE_DOMAIN_IRQ=y | ||||
| CONFIG_HARDWARE_WATCHPOINTS=y | ||||
| CONFIG_HAS_DMA=y | ||||
| CONFIG_HAS_IOMEM=y | ||||
| CONFIG_HAS_IOPORT_MAP=y | ||||
| # CONFIG_HAVE_64BIT_ALIGNED_ACCESS is not set | ||||
| # CONFIG_HAVE_ARCH_BITREVERSE is not set | ||||
| CONFIG_HAVE_ARCH_JUMP_LABEL=y | ||||
| CONFIG_HAVE_ARCH_KGDB=y | ||||
| CONFIG_HAVE_ARCH_SECCOMP_FILTER=y | ||||
| CONFIG_HAVE_ARCH_TRACEHOOK=y | ||||
| # CONFIG_HAVE_BOOTMEM_INFO_NODE is not set | ||||
| CONFIG_HAVE_CBPF_JIT=y | ||||
| CONFIG_HAVE_CC_STACKPROTECTOR=y | ||||
| CONFIG_HAVE_CLK=y | ||||
| CONFIG_HAVE_CONTEXT_TRACKING=y | ||||
| CONFIG_HAVE_C_RECORDMCOUNT=y | ||||
| CONFIG_HAVE_DEBUG_KMEMLEAK=y | ||||
| CONFIG_HAVE_DEBUG_STACKOVERFLOW=y | ||||
| CONFIG_HAVE_DMA_API_DEBUG=y | ||||
| CONFIG_HAVE_DMA_CONTIGUOUS=y | ||||
| CONFIG_HAVE_DYNAMIC_FTRACE=y | ||||
| CONFIG_HAVE_FTRACE_MCOUNT_RECORD=y | ||||
| CONFIG_HAVE_FUNCTION_GRAPH_TRACER=y | ||||
| CONFIG_HAVE_FUNCTION_TRACER=y | ||||
| CONFIG_HAVE_GENERIC_DMA_COHERENT=y | ||||
| CONFIG_HAVE_IDE=y | ||||
| CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK=y | ||||
| CONFIG_HAVE_IRQ_TIME_ACCOUNTING=y | ||||
| CONFIG_HAVE_KVM=y | ||||
| CONFIG_HAVE_LATENCYTOP_SUPPORT=y | ||||
| CONFIG_HAVE_MEMBLOCK=y | ||||
| CONFIG_HAVE_MEMBLOCK_NODE_MAP=y | ||||
| CONFIG_HAVE_MOD_ARCH_SPECIFIC=y | ||||
| CONFIG_HAVE_NET_DSA=y | ||||
| CONFIG_HAVE_OPROFILE=y | ||||
| CONFIG_HAVE_PERF_EVENTS=y | ||||
| CONFIG_HAVE_REGS_AND_STACK_ACCESS_API=y | ||||
| CONFIG_HAVE_SYSCALL_TRACEPOINTS=y | ||||
| CONFIG_HAVE_VIRT_CPU_ACCOUNTING_GEN=y | ||||
| CONFIG_HW_HAS_PCI=y | ||||
| CONFIG_HZ_PERIODIC=y | ||||
| CONFIG_INITRAMFS_SOURCE="" | ||||
| CONFIG_IRQCHIP=y | ||||
| CONFIG_IRQ_DOMAIN=y | ||||
| CONFIG_IRQ_FORCED_THREADING=y | ||||
| CONFIG_IRQ_INTC=y | ||||
| CONFIG_IRQ_MIPS_CPU=y | ||||
| CONFIG_IRQ_WORK=y | ||||
| CONFIG_LIBFDT=y | ||||
| CONFIG_MDIO_BOARDINFO=y | ||||
| CONFIG_MIPS=y | ||||
| CONFIG_MIPS_ASID_BITS=8 | ||||
| CONFIG_MIPS_ASID_SHIFT=0 | ||||
| CONFIG_MIPS_CLOCK_VSYSCALL=y | ||||
| # CONFIG_MIPS_CMDLINE_BUILTIN_EXTEND is not set | ||||
| # CONFIG_MIPS_CMDLINE_DTB_EXTEND is not set | ||||
| # CONFIG_MIPS_CMDLINE_FROM_BOOTLOADER is not set | ||||
| CONFIG_MIPS_CMDLINE_FROM_DTB=y | ||||
| # CONFIG_MIPS_ELF_APPENDED_DTB is not set | ||||
| # CONFIG_MIPS_HUGE_TLB_SUPPORT is not set | ||||
| CONFIG_MIPS_L1_CACHE_SHIFT=5 | ||||
| # CONFIG_MIPS_MACHINE is not set | ||||
| CONFIG_MIPS_NO_APPENDED_DTB=y | ||||
| # CONFIG_MIPS_RAW_APPENDED_DTB is not set | ||||
| CONFIG_MIPS_SPRAM=y | ||||
| CONFIG_MODULES_USE_ELF_REL=y | ||||
| # CONFIG_MTD_CFI_INTELEXT is not set | ||||
| CONFIG_MTD_CMDLINE_PARTS=y | ||||
| CONFIG_MTD_M25P80=y | ||||
| CONFIG_MTD_PHYSMAP=y | ||||
| CONFIG_MTD_SPI_NOR=y | ||||
| CONFIG_MTD_SPI_NOR_USE_4K_SECTORS=y | ||||
| CONFIG_MTD_SPLIT_FIRMWARE=y | ||||
| CONFIG_MTD_SPLIT_SEAMA_FW=y | ||||
| CONFIG_MTD_SPLIT_UIMAGE_FW=y | ||||
| CONFIG_NEED_DMA_MAP_STATE=y | ||||
| CONFIG_NEED_PER_CPU_KM=y | ||||
| CONFIG_NET_MEDIATEK_MDIO=y | ||||
| CONFIG_NET_MEDIATEK_MDIO_RT2880=y | ||||
| CONFIG_NET_MEDIATEK_RT3883=y | ||||
| CONFIG_NET_MEDIATEK_SOC=y | ||||
| CONFIG_NET_VENDOR_MEDIATEK=y | ||||
| CONFIG_NO_GENERIC_PCI_IOPORT_MAP=y | ||||
| # CONFIG_NO_IOPORT_MAP is not set | ||||
| CONFIG_OF=y | ||||
| CONFIG_OF_ADDRESS=y | ||||
| CONFIG_OF_ADDRESS_PCI=y | ||||
| CONFIG_OF_EARLY_FLATTREE=y | ||||
| CONFIG_OF_FLATTREE=y | ||||
| CONFIG_OF_GPIO=y | ||||
| CONFIG_OF_IRQ=y | ||||
| CONFIG_OF_MDIO=y | ||||
| CONFIG_OF_NET=y | ||||
| CONFIG_OF_PCI=y | ||||
| CONFIG_OF_PCI_IRQ=y | ||||
| CONFIG_PCI=y | ||||
| CONFIG_PCI_DOMAINS=y | ||||
| CONFIG_PCI_DRIVERS_LEGACY=y | ||||
| CONFIG_PERF_USE_VMALLOC=y | ||||
| CONFIG_PGTABLE_LEVELS=2 | ||||
| CONFIG_PHYLIB=y | ||||
| CONFIG_PHY_RALINK_USB=y | ||||
| CONFIG_PINCTRL=y | ||||
| CONFIG_PINCTRL_RT2880=y | ||||
| # CONFIG_PINCTRL_SINGLE is not set | ||||
| CONFIG_RALINK=y | ||||
| CONFIG_RALINK_WDT=y | ||||
| # CONFIG_RCU_STALL_COMMON is not set | ||||
| CONFIG_RESET_CONTROLLER=y | ||||
| CONFIG_RTL8366_SMI=y | ||||
| CONFIG_RTL8367B_PHY=y | ||||
| CONFIG_RTL8367_PHY=y | ||||
| CONFIG_SCHED_HRTICK=y | ||||
| # CONFIG_SCHED_INFO is not set | ||||
| # CONFIG_SCSI_DMA is not set | ||||
| # CONFIG_SERIAL_8250_FSL is not set | ||||
| CONFIG_SERIAL_8250_RT288X=y | ||||
| CONFIG_SERIAL_OF_PLATFORM=y | ||||
| # CONFIG_SG_POOL is not set | ||||
| # CONFIG_SOC_MT7620 is not set | ||||
| # CONFIG_SOC_MT7621 is not set | ||||
| # CONFIG_SOC_RT288X is not set | ||||
| # CONFIG_SOC_RT305X is not set | ||||
| CONFIG_SOC_RT3883=y | ||||
| CONFIG_SPI=y | ||||
| CONFIG_SPI_MASTER=y | ||||
| # CONFIG_SPI_MT7621 is not set | ||||
| CONFIG_SPI_RT2880=y | ||||
| CONFIG_SRCU=y | ||||
| CONFIG_SWCONFIG=y | ||||
| CONFIG_SWPHY=y | ||||
| CONFIG_SYSCTL_EXCEPTION_TRACE=y | ||||
| CONFIG_SYS_HAS_CPU_MIPS32_R1=y | ||||
| CONFIG_SYS_HAS_CPU_MIPS32_R2=y | ||||
| CONFIG_SYS_HAS_EARLY_PRINTK=y | ||||
| CONFIG_SYS_SUPPORTS_32BIT_KERNEL=y | ||||
| CONFIG_SYS_SUPPORTS_ARBIT_HZ=y | ||||
| CONFIG_SYS_SUPPORTS_LITTLE_ENDIAN=y | ||||
| CONFIG_SYS_SUPPORTS_MIPS16=y | ||||
| CONFIG_TICK_CPU_ACCOUNTING=y | ||||
| CONFIG_USB_SUPPORT=y | ||||
| CONFIG_USE_OF=y | ||||
| CONFIG_WATCHDOG_CORE=y | ||||
		Reference in New Issue
	
	Block a user
	 John Crispin
					John Crispin