net fec_imx: determine fec version based on device ids
This adds the device id mechanism to the i.MX fec driver and uses it to determine the fec version. Also adds devicetree probing support. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
This commit is contained in:
parent
3e1f8a05b9
commit
258e096e13
|
@ -236,7 +236,7 @@ static int mx28_evk_devices_init(void)
|
|||
|
||||
imx_enable_enetclk();
|
||||
mx28_evk_fec_reset();
|
||||
add_generic_device("fec_imx", 0, NULL, IMX_FEC0_BASE, 0x4000,
|
||||
add_generic_device("imx28-fec", 0, NULL, IMX_FEC0_BASE, 0x4000,
|
||||
IORESOURCE_MEM, &fec_info);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -393,7 +393,7 @@ void base_board_init(void)
|
|||
tx28_get_ethaddr();
|
||||
|
||||
imx_enable_enetclk();
|
||||
add_generic_device("fec_imx", 0, NULL, IMX_FEC0_BASE, 0x4000,
|
||||
add_generic_device("imx28-fec", 0, NULL, IMX_FEC0_BASE, 0x4000,
|
||||
IORESOURCE_MEM, &fec_info);
|
||||
|
||||
ret = register_persistent_environment();
|
||||
|
|
|
@ -8,9 +8,14 @@ static inline struct device_d *imx_add_device(char *name, int id, void *base, in
|
|||
IORESOURCE_MEM, pdata);
|
||||
}
|
||||
|
||||
struct device_d *imx_add_fec(void *base, struct fec_platform_data *pdata)
|
||||
struct device_d *imx_add_fec_imx27(void *base, struct fec_platform_data *pdata)
|
||||
{
|
||||
return imx_add_device("fec_imx", -1, base, 0x1000, pdata);
|
||||
return imx_add_device("imx27-fec", -1, base, 0x1000, pdata);
|
||||
}
|
||||
|
||||
struct device_d *imx_add_fec_imx6(void *base, struct fec_platform_data *pdata)
|
||||
{
|
||||
return imx_add_device("imx6-fec", -1, base, 0x1000, pdata);
|
||||
}
|
||||
|
||||
struct device_d *imx_add_spi(void *base, int id, struct spi_imx_master *pdata)
|
||||
|
|
|
@ -68,7 +68,7 @@ static inline struct device_d *imx25_add_fb(struct imx_fb_platform_data *pdata)
|
|||
|
||||
static inline struct device_d *imx25_add_fec(struct fec_platform_data *pdata)
|
||||
{
|
||||
return imx_add_fec((void *)MX25_FEC_BASE_ADDR, pdata);
|
||||
return imx_add_fec_imx27((void *)MX25_FEC_BASE_ADDR, pdata);
|
||||
}
|
||||
|
||||
static inline struct device_d *imx25_add_mmc0(struct esdhc_platform_data *pdata)
|
||||
|
|
|
@ -53,7 +53,7 @@ static inline struct device_d *imx27_add_fb(struct imx_fb_platform_data *pdata)
|
|||
|
||||
static inline struct device_d *imx27_add_fec(struct fec_platform_data *pdata)
|
||||
{
|
||||
return imx_add_fec((void *)MX27_FEC_BASE_ADDR, pdata);
|
||||
return imx_add_fec_imx27((void *)MX27_FEC_BASE_ADDR, pdata);
|
||||
}
|
||||
|
||||
static inline struct device_d *imx27_add_mmc0(void *pdata)
|
||||
|
|
|
@ -53,7 +53,7 @@ static inline struct device_d *imx35_add_fb(struct imx_ipu_fb_platform_data *pda
|
|||
|
||||
static inline struct device_d *imx35_add_fec(struct fec_platform_data *pdata)
|
||||
{
|
||||
return imx_add_fec((void *)MX35_FEC_BASE_ADDR, pdata);
|
||||
return imx_add_fec_imx27((void *)MX35_FEC_BASE_ADDR, pdata);
|
||||
}
|
||||
|
||||
static inline struct device_d *imx35_add_mmc0(struct esdhc_platform_data *pdata)
|
||||
|
|
|
@ -44,7 +44,7 @@ static inline struct device_d *imx51_add_uart2(void)
|
|||
|
||||
static inline struct device_d *imx51_add_fec(struct fec_platform_data *pdata)
|
||||
{
|
||||
return imx_add_fec((void *)MX51_MXC_FEC_BASE_ADDR, pdata);
|
||||
return imx_add_fec_imx27((void *)MX51_MXC_FEC_BASE_ADDR, pdata);
|
||||
}
|
||||
|
||||
static inline struct device_d *imx51_add_mmc0(struct esdhc_platform_data *pdata)
|
||||
|
|
|
@ -38,7 +38,7 @@ static inline struct device_d *imx53_add_uart2(void)
|
|||
|
||||
static inline struct device_d *imx53_add_fec(struct fec_platform_data *pdata)
|
||||
{
|
||||
return imx_add_fec((void *)MX53_FEC_BASE_ADDR, pdata);
|
||||
return imx_add_fec_imx27((void *)MX53_FEC_BASE_ADDR, pdata);
|
||||
}
|
||||
|
||||
static inline struct device_d *imx53_add_mmc0(struct esdhc_platform_data *pdata)
|
||||
|
|
|
@ -42,7 +42,7 @@ static inline struct device_d *imx6_add_mmc3(struct esdhc_platform_data *pdata)
|
|||
|
||||
static inline struct device_d *imx6_add_fec(struct fec_platform_data *pdata)
|
||||
{
|
||||
return imx_add_fec((void *)MX6_ENET_BASE_ADDR, pdata);
|
||||
return imx_add_fec_imx6((void *)MX6_ENET_BASE_ADDR, pdata);
|
||||
}
|
||||
|
||||
static inline struct device_d *imx6_add_spi0(struct spi_imx_master *pdata)
|
||||
|
|
|
@ -8,7 +8,8 @@
|
|||
#include <mach/imx-ipu-fb.h>
|
||||
#include <mach/esdhc.h>
|
||||
|
||||
struct device_d *imx_add_fec(void *base, struct fec_platform_data *pdata);
|
||||
struct device_d *imx_add_fec_imx27(void *base, struct fec_platform_data *pdata);
|
||||
struct device_d *imx_add_fec_imx6(void *base, struct fec_platform_data *pdata);
|
||||
struct device_d *imx_add_spi(void *base, int id, struct spi_imx_master *pdata);
|
||||
struct device_d *imx_add_i2c(void *base, int id, struct i2c_platform_data *pdata);
|
||||
struct device_d *imx_add_uart_imx1(void *base, int id);
|
||||
|
|
|
@ -310,7 +310,7 @@ static int fec_init(struct eth_device *dev)
|
|||
}
|
||||
|
||||
if (fec->xcv_type == RMII) {
|
||||
if (cpu_is_mx28()) {
|
||||
if (fec_is_imx28(fec)) {
|
||||
rcntl |= FEC_R_CNTRL_RMII_MODE | FEC_R_CNTRL_FCE |
|
||||
FEC_R_CNTRL_NO_LGTH_CHECK;
|
||||
} else {
|
||||
|
@ -340,7 +340,7 @@ static int fec_init(struct eth_device *dev)
|
|||
xwmrk = 0x2;
|
||||
|
||||
/* set ENET tx at store and forward mode */
|
||||
if (cpu_is_mx6())
|
||||
if (fec_is_imx6(fec))
|
||||
xwmrk |= 1 << 8;
|
||||
|
||||
writel(xwmrk, fec->regs + FEC_X_WMRK);
|
||||
|
@ -407,7 +407,7 @@ static int fec_open(struct eth_device *edev)
|
|||
ecr = FEC_ECNTRL_ETHER_EN;
|
||||
|
||||
/* Enable Swap to support little-endian device */
|
||||
if (cpu_is_mx6())
|
||||
if (fec_is_imx6(fec))
|
||||
ecr |= 0x100;
|
||||
|
||||
writel(ecr, fec->regs + FEC_ECNTRL);
|
||||
|
@ -481,7 +481,7 @@ static int fec_send(struct eth_device *dev, void *eth_data, int data_length)
|
|||
* Note: We are always using the first buffer for transmission,
|
||||
* the second will be empty and only used to stop the DMA engine
|
||||
*/
|
||||
if (cpu_is_mx28())
|
||||
if (fec_is_imx28(fec))
|
||||
eth_data = imx28_fix_endianess_wr(eth_data, (data_length + 3) >> 2);
|
||||
|
||||
writew(data_length, &fec->tbd_base[fec->tbd_index].data_length);
|
||||
|
@ -548,7 +548,7 @@ static int fec_recv(struct eth_device *dev)
|
|||
printf("some error: 0x%08x\n", ievent);
|
||||
return 0;
|
||||
}
|
||||
if (!cpu_is_mx28()) {
|
||||
if (!fec_is_imx28(fec)) {
|
||||
if (ievent & FEC_IEVENT_HBERR) {
|
||||
/* Heartbeat error */
|
||||
writel(readl(fec->regs + FEC_X_CNTRL) | 0x1,
|
||||
|
@ -574,7 +574,7 @@ static int fec_recv(struct eth_device *dev)
|
|||
if ((bd_status & FEC_RBD_LAST) && !(bd_status & FEC_RBD_ERR) &&
|
||||
((readw(&rbd->data_length) - 4) > 14)) {
|
||||
|
||||
if (cpu_is_mx28())
|
||||
if (fec_is_imx28(fec))
|
||||
imx28_fix_endianess_rd(
|
||||
phys_to_virt(readl(&rbd->data_pointer)),
|
||||
(readw(&rbd->data_length) + 3) >> 2);
|
||||
|
@ -628,10 +628,17 @@ static int fec_probe(struct device_d *dev)
|
|||
struct fec_priv *fec;
|
||||
void *base;
|
||||
int ret;
|
||||
enum fec_type type;
|
||||
|
||||
ret = dev_get_drvdata(dev, (unsigned long *)&type);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
#ifdef CONFIG_ARCH_IMX27
|
||||
PCCR0 |= PCCR0_FEC_EN;
|
||||
#endif
|
||||
fec = xzalloc(sizeof(*fec));
|
||||
fec->type = type;
|
||||
edev = &fec->edev;
|
||||
dev->priv = fec;
|
||||
edev->priv = fec;
|
||||
|
@ -675,14 +682,19 @@ static int fec_probe(struct device_d *dev)
|
|||
|
||||
fec_alloc_receive_packets(fec, FEC_RBD_NUM, FEC_MAX_PKT_SIZE);
|
||||
|
||||
fec->xcv_type = pdata->xcv_type;
|
||||
if (pdata) {
|
||||
fec->xcv_type = pdata->xcv_type;
|
||||
fec->phy_init = pdata->phy_init;
|
||||
fec->phy_addr = pdata->phy_addr;
|
||||
} else {
|
||||
fec->xcv_type = MII100;
|
||||
fec->phy_addr = -1;
|
||||
}
|
||||
|
||||
if (fec->xcv_type != SEVENWIRE) {
|
||||
fec->phy_init = pdata->phy_init;
|
||||
fec->miibus.read = fec_miibus_read;
|
||||
fec->miibus.write = fec_miibus_write;
|
||||
fec->phy_addr = pdata->phy_addr;
|
||||
switch (pdata->xcv_type) {
|
||||
switch (fec->xcv_type) {
|
||||
case RMII:
|
||||
fec->interface = PHY_INTERFACE_MODE_RMII;
|
||||
break;
|
||||
|
@ -719,13 +731,45 @@ static void fec_remove(struct device_d *dev)
|
|||
fec_halt(&fec->edev);
|
||||
}
|
||||
|
||||
static __maybe_unused struct of_device_id imx_fec_dt_ids[] = {
|
||||
{
|
||||
.compatible = "fsl,imx27-fec",
|
||||
.data = FEC_TYPE_IMX27,
|
||||
}, {
|
||||
.compatible = "fsl,imx28-fec",
|
||||
.data = FEC_TYPE_IMX28,
|
||||
}, {
|
||||
.compatible = "fsl,imx6q-fec",
|
||||
.data = FEC_TYPE_IMX6,
|
||||
}, {
|
||||
/* sentinel */
|
||||
}
|
||||
};
|
||||
|
||||
static struct platform_device_id imx_fec_ids[] = {
|
||||
{
|
||||
.name = "imx27-fec",
|
||||
.driver_data = (unsigned long)FEC_TYPE_IMX27,
|
||||
}, {
|
||||
.name = "imx28-fec",
|
||||
.driver_data = (unsigned long)FEC_TYPE_IMX28,
|
||||
}, {
|
||||
.name = "imx6-fec",
|
||||
.driver_data = (unsigned long)FEC_TYPE_IMX6,
|
||||
}, {
|
||||
/* sentinel */
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Driver description for registering
|
||||
*/
|
||||
static struct driver_d fec_driver = {
|
||||
.name = "fec_imx",
|
||||
.probe = fec_probe,
|
||||
.name = "fec_imx",
|
||||
.probe = fec_probe,
|
||||
.remove = fec_remove,
|
||||
.of_compatible = DRV_OF_COMPAT(imx_fec_dt_ids),
|
||||
.id_table = imx_fec_ids,
|
||||
};
|
||||
|
||||
static int fec_register(void)
|
||||
|
|
|
@ -122,6 +122,12 @@ struct buffer_descriptor {
|
|||
uint32_t data_pointer; /**< payload's buffer address */
|
||||
};
|
||||
|
||||
enum fec_type {
|
||||
FEC_TYPE_IMX27,
|
||||
FEC_TYPE_IMX28,
|
||||
FEC_TYPE_IMX6,
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief i.MX27-FEC private structure
|
||||
*/
|
||||
|
@ -139,8 +145,24 @@ struct fec_priv {
|
|||
struct mii_bus miibus;
|
||||
void (*phy_init)(struct phy_device *dev);
|
||||
struct clk *clk;
|
||||
enum fec_type type;
|
||||
};
|
||||
|
||||
static inline int fec_is_imx27(struct fec_priv *priv)
|
||||
{
|
||||
return priv->type == FEC_TYPE_IMX27;
|
||||
}
|
||||
|
||||
static inline int fec_is_imx28(struct fec_priv *priv)
|
||||
{
|
||||
return priv->type == FEC_TYPE_IMX28;
|
||||
}
|
||||
|
||||
static inline int fec_is_imx6(struct fec_priv *priv)
|
||||
{
|
||||
return priv->type == FEC_TYPE_IMX6;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Numbers of buffer descriptors for receiving
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue