mirror of
https://github.com/torvalds/linux.git
synced 2024-12-05 02:23:16 +00:00
ARM: Orion: Eth: Add clk/clkdev support.
The t_clk is moved from the shared part of the ethernet driver into the per port section. Each port can have its own gated clock, which it needs to enable/disable, as oppossed to there being one clock shared by all ports. In practice, only kirkwood supports this at the moment. Signed-off-by: Andrew Lunn <andrew@lunn.ch> Tested-by: Jamie Lentin <jm@lentin.co.uk> Signed-off-by: Mike Turquette <mturquette@linaro.org>
This commit is contained in:
parent
4574b88669
commit
452503ebc7
@ -102,8 +102,7 @@ void __init dove_ehci1_init(void)
|
||||
void __init dove_ge00_init(struct mv643xx_eth_platform_data *eth_data)
|
||||
{
|
||||
orion_ge00_init(eth_data,
|
||||
DOVE_GE00_PHYS_BASE, IRQ_DOVE_GE00_SUM,
|
||||
0, get_tclk());
|
||||
DOVE_GE00_PHYS_BASE, IRQ_DOVE_GE00_SUM, 0);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
|
@ -86,14 +86,14 @@ static struct clk __init *kirkwood_register_gate(const char *name, u8 bit_idx)
|
||||
|
||||
void __init kirkwood_clk_init(void)
|
||||
{
|
||||
struct clk *runit;
|
||||
struct clk *runit, *ge0, *ge1;
|
||||
|
||||
tclk = clk_register_fixed_rate(NULL, "tclk", NULL,
|
||||
CLK_IS_ROOT, kirkwood_tclk);
|
||||
|
||||
runit = kirkwood_register_gate("runit", CGC_BIT_RUNIT);
|
||||
kirkwood_register_gate("ge0", CGC_BIT_GE0);
|
||||
kirkwood_register_gate("ge1", CGC_BIT_GE1);
|
||||
ge0 = kirkwood_register_gate("ge0", CGC_BIT_GE0);
|
||||
ge1 = kirkwood_register_gate("ge1", CGC_BIT_GE1);
|
||||
kirkwood_register_gate("sata0", CGC_BIT_SATA0);
|
||||
kirkwood_register_gate("sata1", CGC_BIT_SATA1);
|
||||
kirkwood_register_gate("usb0", CGC_BIT_USB0);
|
||||
@ -110,6 +110,8 @@ void __init kirkwood_clk_init(void)
|
||||
/* clkdev entries, mapping clks to devices */
|
||||
orion_clkdev_add(NULL, "orion_spi.0", runit);
|
||||
orion_clkdev_add(NULL, "orion_spi.1", runit);
|
||||
orion_clkdev_add(NULL, MV643XX_ETH_NAME ".0", ge0);
|
||||
orion_clkdev_add(NULL, MV643XX_ETH_NAME ".1", ge1);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
@ -131,7 +133,7 @@ void __init kirkwood_ge00_init(struct mv643xx_eth_platform_data *eth_data)
|
||||
|
||||
orion_ge00_init(eth_data,
|
||||
GE00_PHYS_BASE, IRQ_KIRKWOOD_GE00_SUM,
|
||||
IRQ_KIRKWOOD_GE00_ERR, kirkwood_tclk);
|
||||
IRQ_KIRKWOOD_GE00_ERR);
|
||||
}
|
||||
|
||||
|
||||
@ -145,7 +147,7 @@ void __init kirkwood_ge01_init(struct mv643xx_eth_platform_data *eth_data)
|
||||
|
||||
orion_ge01_init(eth_data,
|
||||
GE01_PHYS_BASE, IRQ_KIRKWOOD_GE01_SUM,
|
||||
IRQ_KIRKWOOD_GE01_ERR, kirkwood_tclk);
|
||||
IRQ_KIRKWOOD_GE01_ERR);
|
||||
}
|
||||
|
||||
|
||||
|
@ -213,7 +213,7 @@ void __init mv78xx0_ge00_init(struct mv643xx_eth_platform_data *eth_data)
|
||||
{
|
||||
orion_ge00_init(eth_data,
|
||||
GE00_PHYS_BASE, IRQ_MV78XX0_GE00_SUM,
|
||||
IRQ_MV78XX0_GE_ERR, get_tclk());
|
||||
IRQ_MV78XX0_GE_ERR);
|
||||
}
|
||||
|
||||
|
||||
@ -224,7 +224,7 @@ void __init mv78xx0_ge01_init(struct mv643xx_eth_platform_data *eth_data)
|
||||
{
|
||||
orion_ge01_init(eth_data,
|
||||
GE01_PHYS_BASE, IRQ_MV78XX0_GE01_SUM,
|
||||
NO_IRQ, get_tclk());
|
||||
NO_IRQ);
|
||||
}
|
||||
|
||||
|
||||
@ -248,7 +248,7 @@ void __init mv78xx0_ge10_init(struct mv643xx_eth_platform_data *eth_data)
|
||||
|
||||
orion_ge10_init(eth_data,
|
||||
GE10_PHYS_BASE, IRQ_MV78XX0_GE10_SUM,
|
||||
NO_IRQ, get_tclk());
|
||||
NO_IRQ);
|
||||
}
|
||||
|
||||
|
||||
@ -272,7 +272,7 @@ void __init mv78xx0_ge11_init(struct mv643xx_eth_platform_data *eth_data)
|
||||
|
||||
orion_ge11_init(eth_data,
|
||||
GE11_PHYS_BASE, IRQ_MV78XX0_GE11_SUM,
|
||||
NO_IRQ, get_tclk());
|
||||
NO_IRQ);
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
|
@ -109,7 +109,7 @@ void __init orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data)
|
||||
{
|
||||
orion_ge00_init(eth_data,
|
||||
ORION5X_ETH_PHYS_BASE, IRQ_ORION5X_ETH_SUM,
|
||||
IRQ_ORION5X_ETH_ERR, orion5x_tclk);
|
||||
IRQ_ORION5X_ETH_ERR);
|
||||
}
|
||||
|
||||
|
||||
|
@ -43,6 +43,10 @@ void __init orion_clkdev_init(struct clk *tclk)
|
||||
{
|
||||
orion_clkdev_add(NULL, "orion_spi.0", tclk);
|
||||
orion_clkdev_add(NULL, "orion_spi.1", tclk);
|
||||
orion_clkdev_add(NULL, MV643XX_ETH_NAME ".0", tclk);
|
||||
orion_clkdev_add(NULL, MV643XX_ETH_NAME ".1", tclk);
|
||||
orion_clkdev_add(NULL, MV643XX_ETH_NAME ".2", tclk);
|
||||
orion_clkdev_add(NULL, MV643XX_ETH_NAME ".3", tclk);
|
||||
}
|
||||
|
||||
/* Fill in the resources structure and link it into the platform
|
||||
@ -225,13 +229,11 @@ void __init orion_rtc_init(unsigned long mapbase,
|
||||
****************************************************************************/
|
||||
static __init void ge_complete(
|
||||
struct mv643xx_eth_shared_platform_data *orion_ge_shared_data,
|
||||
int tclk,
|
||||
struct resource *orion_ge_resource, unsigned long irq,
|
||||
struct platform_device *orion_ge_shared,
|
||||
struct mv643xx_eth_platform_data *eth_data,
|
||||
struct platform_device *orion_ge)
|
||||
{
|
||||
orion_ge_shared_data->t_clk = tclk;
|
||||
orion_ge_resource->start = irq;
|
||||
orion_ge_resource->end = irq;
|
||||
eth_data->shared = orion_ge_shared;
|
||||
@ -282,12 +284,11 @@ static struct platform_device orion_ge00 = {
|
||||
void __init orion_ge00_init(struct mv643xx_eth_platform_data *eth_data,
|
||||
unsigned long mapbase,
|
||||
unsigned long irq,
|
||||
unsigned long irq_err,
|
||||
int tclk)
|
||||
unsigned long irq_err)
|
||||
{
|
||||
fill_resources(&orion_ge00_shared, orion_ge00_shared_resources,
|
||||
mapbase + 0x2000, SZ_16K - 1, irq_err);
|
||||
ge_complete(&orion_ge00_shared_data, tclk,
|
||||
ge_complete(&orion_ge00_shared_data,
|
||||
orion_ge00_resources, irq, &orion_ge00_shared,
|
||||
eth_data, &orion_ge00);
|
||||
}
|
||||
@ -335,12 +336,11 @@ static struct platform_device orion_ge01 = {
|
||||
void __init orion_ge01_init(struct mv643xx_eth_platform_data *eth_data,
|
||||
unsigned long mapbase,
|
||||
unsigned long irq,
|
||||
unsigned long irq_err,
|
||||
int tclk)
|
||||
unsigned long irq_err)
|
||||
{
|
||||
fill_resources(&orion_ge01_shared, orion_ge01_shared_resources,
|
||||
mapbase + 0x2000, SZ_16K - 1, irq_err);
|
||||
ge_complete(&orion_ge01_shared_data, tclk,
|
||||
ge_complete(&orion_ge01_shared_data,
|
||||
orion_ge01_resources, irq, &orion_ge01_shared,
|
||||
eth_data, &orion_ge01);
|
||||
}
|
||||
@ -388,12 +388,11 @@ static struct platform_device orion_ge10 = {
|
||||
void __init orion_ge10_init(struct mv643xx_eth_platform_data *eth_data,
|
||||
unsigned long mapbase,
|
||||
unsigned long irq,
|
||||
unsigned long irq_err,
|
||||
int tclk)
|
||||
unsigned long irq_err)
|
||||
{
|
||||
fill_resources(&orion_ge10_shared, orion_ge10_shared_resources,
|
||||
mapbase + 0x2000, SZ_16K - 1, irq_err);
|
||||
ge_complete(&orion_ge10_shared_data, tclk,
|
||||
ge_complete(&orion_ge10_shared_data,
|
||||
orion_ge10_resources, irq, &orion_ge10_shared,
|
||||
eth_data, &orion_ge10);
|
||||
}
|
||||
@ -441,12 +440,11 @@ static struct platform_device orion_ge11 = {
|
||||
void __init orion_ge11_init(struct mv643xx_eth_platform_data *eth_data,
|
||||
unsigned long mapbase,
|
||||
unsigned long irq,
|
||||
unsigned long irq_err,
|
||||
int tclk)
|
||||
unsigned long irq_err)
|
||||
{
|
||||
fill_resources(&orion_ge11_shared, orion_ge11_shared_resources,
|
||||
mapbase + 0x2000, SZ_16K - 1, irq_err);
|
||||
ge_complete(&orion_ge11_shared_data, tclk,
|
||||
ge_complete(&orion_ge11_shared_data,
|
||||
orion_ge11_resources, irq, &orion_ge11_shared,
|
||||
eth_data, &orion_ge11);
|
||||
}
|
||||
|
@ -39,29 +39,26 @@ void __init orion_rtc_init(unsigned long mapbase,
|
||||
void __init orion_ge00_init(struct mv643xx_eth_platform_data *eth_data,
|
||||
unsigned long mapbase,
|
||||
unsigned long irq,
|
||||
unsigned long irq_err,
|
||||
int tclk);
|
||||
unsigned long irq_err);
|
||||
|
||||
void __init orion_ge01_init(struct mv643xx_eth_platform_data *eth_data,
|
||||
unsigned long mapbase,
|
||||
unsigned long irq,
|
||||
unsigned long irq_err,
|
||||
int tclk);
|
||||
unsigned long irq_err);
|
||||
|
||||
void __init orion_ge10_init(struct mv643xx_eth_platform_data *eth_data,
|
||||
unsigned long mapbase,
|
||||
unsigned long irq,
|
||||
unsigned long irq_err,
|
||||
int tclk);
|
||||
unsigned long irq_err);
|
||||
|
||||
void __init orion_ge11_init(struct mv643xx_eth_platform_data *eth_data,
|
||||
unsigned long mapbase,
|
||||
unsigned long irq,
|
||||
unsigned long irq_err,
|
||||
int tclk);
|
||||
unsigned long irq_err);
|
||||
|
||||
void __init orion_ge00_switch_init(struct dsa_platform_data *d,
|
||||
int irq);
|
||||
|
||||
void __init orion_i2c_init(unsigned long mapbase,
|
||||
unsigned long irq,
|
||||
unsigned long freq_m);
|
||||
|
@ -57,6 +57,7 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/inet_lro.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/clk.h>
|
||||
|
||||
static char mv643xx_eth_driver_name[] = "mv643xx_eth";
|
||||
static char mv643xx_eth_driver_version[] = "1.4";
|
||||
@ -289,10 +290,10 @@ struct mv643xx_eth_shared_private {
|
||||
/*
|
||||
* Hardware-specific parameters.
|
||||
*/
|
||||
unsigned int t_clk;
|
||||
int extended_rx_coal_limit;
|
||||
int tx_bw_control;
|
||||
int tx_csum_limit;
|
||||
|
||||
};
|
||||
|
||||
#define TX_BW_CONTROL_ABSENT 0
|
||||
@ -431,6 +432,12 @@ struct mv643xx_eth_private {
|
||||
int tx_desc_sram_size;
|
||||
int txq_count;
|
||||
struct tx_queue txq[8];
|
||||
|
||||
/*
|
||||
* Hardware-specific parameters.
|
||||
*/
|
||||
struct clk *clk;
|
||||
unsigned int t_clk;
|
||||
};
|
||||
|
||||
|
||||
@ -1010,7 +1017,7 @@ static void tx_set_rate(struct mv643xx_eth_private *mp, int rate, int burst)
|
||||
int mtu;
|
||||
int bucket_size;
|
||||
|
||||
token_rate = ((rate / 1000) * 64) / (mp->shared->t_clk / 1000);
|
||||
token_rate = ((rate / 1000) * 64) / (mp->t_clk / 1000);
|
||||
if (token_rate > 1023)
|
||||
token_rate = 1023;
|
||||
|
||||
@ -1042,7 +1049,7 @@ static void txq_set_rate(struct tx_queue *txq, int rate, int burst)
|
||||
int token_rate;
|
||||
int bucket_size;
|
||||
|
||||
token_rate = ((rate / 1000) * 64) / (mp->shared->t_clk / 1000);
|
||||
token_rate = ((rate / 1000) * 64) / (mp->t_clk / 1000);
|
||||
if (token_rate > 1023)
|
||||
token_rate = 1023;
|
||||
|
||||
@ -1309,7 +1316,7 @@ static unsigned int get_rx_coal(struct mv643xx_eth_private *mp)
|
||||
temp = (val & 0x003fff00) >> 8;
|
||||
|
||||
temp *= 64000000;
|
||||
do_div(temp, mp->shared->t_clk);
|
||||
do_div(temp, mp->t_clk);
|
||||
|
||||
return (unsigned int)temp;
|
||||
}
|
||||
@ -1319,7 +1326,7 @@ static void set_rx_coal(struct mv643xx_eth_private *mp, unsigned int usec)
|
||||
u64 temp;
|
||||
u32 val;
|
||||
|
||||
temp = (u64)usec * mp->shared->t_clk;
|
||||
temp = (u64)usec * mp->t_clk;
|
||||
temp += 31999999;
|
||||
do_div(temp, 64000000);
|
||||
|
||||
@ -1345,7 +1352,7 @@ static unsigned int get_tx_coal(struct mv643xx_eth_private *mp)
|
||||
|
||||
temp = (rdlp(mp, TX_FIFO_URGENT_THRESHOLD) & 0x3fff0) >> 4;
|
||||
temp *= 64000000;
|
||||
do_div(temp, mp->shared->t_clk);
|
||||
do_div(temp, mp->t_clk);
|
||||
|
||||
return (unsigned int)temp;
|
||||
}
|
||||
@ -1354,7 +1361,7 @@ static void set_tx_coal(struct mv643xx_eth_private *mp, unsigned int usec)
|
||||
{
|
||||
u64 temp;
|
||||
|
||||
temp = (u64)usec * mp->shared->t_clk;
|
||||
temp = (u64)usec * mp->t_clk;
|
||||
temp += 31999999;
|
||||
do_div(temp, 64000000);
|
||||
|
||||
@ -2662,10 +2669,6 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
|
||||
if (dram)
|
||||
mv643xx_eth_conf_mbus_windows(msp, dram);
|
||||
|
||||
/*
|
||||
* Detect hardware parameters.
|
||||
*/
|
||||
msp->t_clk = (pd != NULL && pd->t_clk != 0) ? pd->t_clk : 133000000;
|
||||
msp->tx_csum_limit = (pd != NULL && pd->tx_csum_limit) ?
|
||||
pd->tx_csum_limit : 9 * 1024;
|
||||
infer_hw_params(msp);
|
||||
@ -2890,6 +2893,18 @@ static int mv643xx_eth_probe(struct platform_device *pdev)
|
||||
|
||||
mp->dev = dev;
|
||||
|
||||
/*
|
||||
* Get the clk rate, if there is one, otherwise use the default.
|
||||
*/
|
||||
mp->clk = clk_get(&pdev->dev, (pdev->id ? "1" : "0"));
|
||||
if (!IS_ERR(mp->clk)) {
|
||||
clk_prepare_enable(mp->clk);
|
||||
mp->t_clk = clk_get_rate(mp->clk);
|
||||
} else {
|
||||
mp->t_clk = 133000000;
|
||||
printk(KERN_WARNING "Unable to get clock");
|
||||
}
|
||||
|
||||
set_params(mp, pd);
|
||||
netif_set_real_num_tx_queues(dev, mp->txq_count);
|
||||
netif_set_real_num_rx_queues(dev, mp->rxq_count);
|
||||
@ -2978,6 +2993,11 @@ static int mv643xx_eth_remove(struct platform_device *pdev)
|
||||
if (mp->phy != NULL)
|
||||
phy_detach(mp->phy);
|
||||
cancel_work_sync(&mp->tx_timeout_task);
|
||||
|
||||
if (!IS_ERR(mp->clk)) {
|
||||
clk_disable_unprepare(mp->clk);
|
||||
clk_put(mp->clk);
|
||||
}
|
||||
free_netdev(mp->dev);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
@ -18,7 +18,6 @@
|
||||
struct mv643xx_eth_shared_platform_data {
|
||||
struct mbus_dram_target_info *dram;
|
||||
struct platform_device *shared_smi;
|
||||
unsigned int t_clk;
|
||||
/*
|
||||
* Max packet size for Tx IP/Layer 4 checksum, when set to 0, default
|
||||
* limit of 9KiB will be used.
|
||||
|
Loading…
Reference in New Issue
Block a user