This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

To change EVM code of TI814X-LINUX-PSP-04.01.00.05 to support the RMII mode on custom board

Hi,

 Code flow for EVM board is as follows

arch/arm/mach-omap2/board-ti8148evm.c

----------------------------------------------------------

MACHINE_START(TI8148EVM, "ti8148evm")

     /* Maintainer: Texas Instruments */

         .boot_params    = 0x80000100,

         .map_io         = ti8148_evm_map_io,

         .reserve         = ti81xx_reserve,

         .init_irq       = ti8148_evm_init_irq,

         .init_machine   = ti8148_evm_init,

         .timer          = &omap_timer,

 MACHINE_END

 

48 #ifdef CONFIG_OMAP_MUX

 49 static struct omap_board_mux board_mux[] __initdata = {

 50         { .reg_offset = OMAP_MUX_TERMINATOR },

 51 };

 52 #else

 53 #define board_mux     NULL

 54 #endif

 

static void __init ti8148_evm_init(void)

271 {

272         printk(KERN_CRIT "ETHERNET:inside ti8148_evm_init b4 calling the ti814x_mux_init\n");

273         ti814x_mux_init(board_mux);

 

arch/arm/mach-omap2/muxti814x.c

------------------------------------------------

int __init ti814x_mux_init(struct omap_board_mux *board_subset)

833 {

834         printk(KERN_CRIT "ETHERNET:Inside the ti814x_mux_init b4 calling omap_mux_init with 8 args\n");

835         return omap_mux_init("core", OMAP_MUX_REG_32BIT,

836                         TI81XX_CONTROL_PADCONF_MUX_PBASE,

837                         TI814X_CONTROL_PADCONF_MUX_SIZE, ti814x_muxmodes, NULL,

838                         board_subset, NULL);

839 }

 

arch/arm/mach-omap2/mux.c

----------------------------------------

1023 int __init omap_mux_init(const char *name, u32 flags,

1024                          u32 mux_pbase, u32 mux_size,

1025                          struct omap_mux *superset,

1026                          struct omap_mux *package_subset,

1027                          struct omap_board_mux *board_mux,

1028                          struct omap_ball *package_balls)

1029 {

1030         struct omap_mux_partition *partition;

1031

1032         printk(KERN_CRIT "ETHERNET:inside the omap_mux_init\n");

1033         partition = kzalloc(sizeof(struct omap_mux_partition), GFP_KERNEL);

1034         if (!partition)

1035                 return -ENOMEM;

1036

1037         partition->name = name;

1038         partition->flags = flags;

1039         partition->size = mux_size;

1040         partition->phys = mux_pbase;

1041         partition->base = ioremap(mux_pbase, mux_size);

1042         if (!partition->base) {

1043                 pr_err("%s: Could not ioremap mux partition at 0x%08x\n",

1044                         __func__, partition->phys);

1045                 return -ENODEV;

1046         }

1047

1048         INIT_LIST_HEAD(&partition->muxmodes);

1049

1050         list_add_tail(&partition->node, &mux_partitions);

1051         mux_partitions_cnt++;

1052         pr_info("%s: Add partition: #%d: %s, flags: %x\n", __func__,

1053                 mux_partitions_cnt, partition->name, partition->flags);

1054

1055         omap_mux_init_package(superset, package_subset, package_balls);

1056         omap_mux_init_list(partition, superset);

1057         omap_mux_init_signals(partition, board_mux);

1058

1059         return 0;

1060 }

 

998 static void omap_mux_init_signals(struct omap_mux_partition *partition,

 999                                   struct omap_board_mux *board_mux)

1000 {

1001         printk(KERN_CRIT "ETHERNET:inside omap_mux_init_signals b4 calling omap_mux_set_cmdline_signals\n");

1002         omap_mux_set_cmdline_signals();

1003         omap_mux_write_array(partition, board_mux);

1004 }

 

785 static void __init omap_mux_set_cmdline_signals(void)

 786 {

 787         char *options, *next_opt, *token;

 788

 789         printk(KERN_CRIT "ETHERNET:inside omap_mux_set_cmdline_signals\n");

 790

 791         if (!omap_mux_options)

{                   printk(KERN_CRIT”gets returned here\n”);

                return;

}

 793

 794         options = kmalloc(strlen(omap_mux_options) + 1, GFP_KERNEL);

 795         if (!options)

 796                 return;

 797

 798         strcpy(options, omap_mux_options);

 799         next_opt = options;

 800

 801         while ((token = strsep(&next_opt, ",")) != NULL) {

 802                 char *keyval, *name;

 803                 unsigned long val;

 804

 805                 keyval = token;

 806                 name = strsep(&keyval, "=");

 807                 if (name) {

 808                         int res;

 809

 810                         res = strict_strtoul(keyval, 0x10, &val);

 811                         if (res < 0)

 812                                 continue;

 813

 814                         printk(KERN_CRIT "ETHERNET:inside while of omap_mux_set_cmdline_signals\n");

 815                         omap_mux_init_signal(name, (int)val);

 816                 }

 817         }

 818

 819         kfree(options);

 820 }          

253 int __init omap_mux_init_signal(const char *muxname, int val)

 254 {

 255         struct omap_mux_partition *partition = NULL;

 256         struct omap_mux *mux = NULL;

 257         u16 old_mode;

 258         int mux_mode;

 259

 260         printk(KERN_CRIT "ETHERNET:inside omap_mux_init_signal\n");

 261         mux_mode = omap_mux_get_by_name(muxname, &partition, &mux);

 262         if (mux_mode < 0)

 263                 return mux_mode;

 264

 265         old_mode = omap_mux_read(partition, mux->reg_offset);

 266

 267         mux_mode |= val;

 268         pr_debug("%s: Setting signal %s 0x%04x -> 0x%04x\n",

 269                          __func__, muxname, old_mode, mux_mode);

 270         omap_mux_write(partition, mux_mode, mux->reg_offset);

 271

 272         return 0;

 273 }

76 void omap_mux_write(struct omap_mux_partition *partition, u32 val,

  77                            u16 reg)

  78 {

  79         /* Avoid unintentional change of bits 18-31 on TI814x */

  80         //printk(KERN_CRIT "ETHERNET:inside the omap_mux_write\n");

  81         printk(KERN_CRIT "ETHERNET:inside the omap_mux_write\n");

  82         if (cpu_is_ti814x())

  83                 val |= __raw_readl(partition->base + reg) & 0xFFFC0000;

  84

  85         if (partition->flags & OMAP_MUX_REG_8BIT)

  86                 __raw_writeb(val, partition->base + reg);

  87         if (partition->flags & OMAP_MUX_REG_32BIT)

  88                 __raw_writel(val, partition->base + reg);

  89         else

  90                 __raw_writew(val, partition->base + reg);

  91 }

 

93 void omap_mux_write_array(struct omap_mux_partition *partition,

  94                                  struct omap_board_mux *board_mux)

  95 {

  96         printk(KERN_CRIT "ETHERNET:inside omap_mux_write_array\n");

  97         while (board_mux->reg_offset != OMAP_MUX_TERMINATOR) {

  98                 printk(KERN_CRIT "ETHERNET:inside omap_mux_write_array\n");

  99                 omap_mux_write(partition, board_mux->value,

 100                                board_mux->reg_offset);

 101                 board_mux++;

 102         }

#ifdef CONFIG_OMAP_MUX

 

#define _TI814X_MUXENTRY(M0, g, m0, m1, m2, m3, m4, m5, m6, m7)                  \

{                                                                                                                                               \

                .reg_offset            = (TI814X_CONTROL_PADCONF_##M0##_OFFSET),    \

                .gpio                       = (g),                                                                                       \

                .muxnames            = { m0, m1, m2, m3, m4, m5, m6, m7 },                            \

}

 

/*

 * Superset of all mux modes for TI814X

 */

static struct omap_mux __initdata ti814x_muxmodes[] = {

                _TI814X_MUXENTRY(MMC1_CLK, 0,

                                                "mmc1_clk", NULL, NULL, NULL,

                                       :

                                      :

                                     :

              

_TI814X_MUXENTRY(GMII0_COL, 0,

                                                "gmii0_col", "vin1b_d1", "rmii0_rxd0", NULL, NULL, NULL,

                                                NULL, "gpio3_24"),

                _TI814X_MUXENTRY(GMII0_CRS, 0,

                                                "gmii0_crs", "vin1b_d2", "rmii0_rxd1", NULL, NULL, NULL,

                                                NULL, "gpio3_25"),

                _TI814X_MUXENTRY(GMII0_RXER, 0,

                                                "gmii0_rxer", "vin1b_d3", "rmii0_rxer", NULL, NULL,

                                                NULL, NULL, "gpio3_26"),

                _TI814X_MUXENTRY(GMII0_RXCLK, 0,

                                                "gmii0_rxclk", "vin1b_d4", "rmii0_crs", NULL, NULL,

                                                "spi3_cs2", NULL, "gpio3_27"),

                _TI814X_MUXENTRY(GMII0_RXD0, 0,

                                                "gmii0_rxd0", "vin1b_d5", "rmii0_txd0", NULL, NULL,

                                                NULL, NULL, "gpio3_28"),

                _TI814X_MUXENTRY(GMII0_RXD1, 0,

                                                "gmii0_rxd1", "vin1b_d6", "rmii0_txd1", NULL, NULL,

                                                NULL, NULL, "gpio3_29"),

                _TI814X_MUXENTRY(GMII0_RXD2, 0,

                                                "gmii0_rxd2", "vin1b_d7", "rmii0_txen", NULL, NULL,

                                                NULL, NULL, "gpio3_30_mux0"),

 

                                               :

 

                                               :

                                                :

                                              :

                _TI814X_MUXENTRY(RMII_REFCLK, 0,

                                                "rmii_refclk", NULL, NULL, NULL, NULL, NULL,

                                                "timer2_mux3", "gpio1_10_mux0"),

                _TI814X_MUXENTRY(MDIO_MCLK, 0,

                                                "mdio_mclk", NULL, NULL, NULL, NULL, NULL, NULL,

                                                "gpio1_11_mux0"),

                _TI814X_MUXENTRY(MDIO_D, 0,

                                                "mdio_d", NULL, NULL, NULL, NULL, NULL, NULL,

                                                "gpio1_12_mux0"),

                                           :

                                         :

                                            :

After all the above thing we come for

 

 

arch/arm/mach-omap2/devices.c#

============================

#ifdef CONFIG_ARCH_TI814X
#define TI814X_CPSW_BASE  (0x4A100000)
#define TI814X_CPSW_MDIO_BASE  (0x4A100800)
#define TI814X_CPSW_SS_BASE  (0x4A100900)
#define TI814X_EMAC_MDIO_FREQ  (1000000)

static u64 cpsw_dma_mask = DMA_BIT_MASK(32);
/* TODO : Verify the offsets */
struct cpsw_slave_data cpsw_slaves[] = {
 {
  .slave_reg_ofs  = 0x50,
  .sliver_reg_ofs = 0x700,
  .phy_id  = "0:00",
 },
 {
  .slave_reg_ofs  = 0x90,
  .sliver_reg_ofs = 0x740,
  .phy_id  = "0:01",
 },
};

static struct cpsw_platform_data ti814x_cpsw_pdata = {
 .ss_reg_ofs  = 0x900,
 .channels  = 8,
 .cpdma_reg_ofs  = 0x100,
 .slaves   = 1,
 .slave_data  = cpsw_slaves,
 .ale_reg_ofs  = 0x600,
 .ale_entries  = 1024,
 .host_port_reg_ofs      = 0x28,
 .hw_stats_reg_ofs       = 0x400,
 .bd_ram_ofs  = 0x2000,
 .bd_ram_size  = SZ_8K,
 .rx_descs               = 64,
 .mac_control            = BIT(5), /* MIIEN */
 .gigabit_en  = 1,
 .host_port_num  = 0,
 .no_bd_ram  = false,
};

static struct resource ti814x_cpsw_resources[] = {
 {
  .start  = TI814X_CPSW_BASE,
  .end    = TI814X_CPSW_BASE + SZ_2K - 1,
  .flags  = IORESOURCE_MEM,
 },
 {
  .start  = TI814X_CPSW_SS_BASE,
  .end    = TI814X_CPSW_SS_BASE + SZ_256 - 1,
  .flags  = IORESOURCE_MEM,
 },
 {
  .start = TI814X_IRQ_GSWRXTHR0,
  .end = TI814X_IRQ_GSWRXTHR0,
  .flags = IORESOURCE_IRQ,
 },
 {
  .start = TI814X_IRQ_GSWRXINT0,
  .end = TI814X_IRQ_GSWRXINT0,
  .flags = IORESOURCE_IRQ,
 },
 {
  .start = TI814X_IRQ_GSWTXINT0,
  .end = TI814X_IRQ_GSWTXINT0,
  .flags = IORESOURCE_IRQ,
 },
 {
  .start = TI814X_IRQ_GSWMISC0,
  .end = TI814X_IRQ_GSWMISC0,
  .flags = IORESOURCE_IRQ,
 },
};

static struct platform_device ti814x_cpsw_device = {
 .name  = "cpsw",
 .id  = 0,
 .num_resources = ARRAY_SIZE(ti814x_cpsw_resources),
 .resource = ti814x_cpsw_resources,
 .dev  = {
     .platform_data    = &ti814x_cpsw_pdata,
     .dma_mask    = &cpsw_dma_mask,
     .coherent_dma_mask = DMA_BIT_MASK(32),
    },
};

static int __init omap2_init_devices(void)

{

                /*

                 * please keep these calls, and their implementations above,

                 * in alphabetical order so they're easier to sort through.

                 */

                omap_hsmmc_reset();

#if !defined(CONFIG_ARCH_TI81XX)

                omap_init_audio();

#endif

                omap_init_camera();

                omap_init_mbox();

                omap_init_mcspi();

                omap_init_pmu();

                omap_hdq_init();

                omap_init_sti();

                omap_init_sham();

                omap_init_aes();

                omap_init_vout();

#ifdef CONFIG_ARCH_TI81XX

                ti81xx_ethernet_init();

                ti816x_init_pcie();

                ti81xx_register_edma();

                ti81xx_init_pcm();

                ti816x_sr_init();

#endif

                omap_init_ahci();

                return 0;

}

arch_initcall(omap2_init_devices);

 

1879 #ifdef CONFIG_ARCH_TI81XX

1880 static void ti81xx_ethernet_init(void)

1881 {

1882         printk(KERN_CRIT "ETHERNET:inside ti81xx_ethernet_init\n");

1883         if (cpu_is_ti816x())

1884                 ti816x_ethernet_init();

1885         else

1886                 ti814x_cpsw_init();

1887 }

 

void ti814x_cpsw_init(void)

{

                u32 mac_lo, mac_hi;

 

                printk(KERN_CRIT "ETHERNET:inside ti814x_cpsw_init\n");

                mac_lo = omap_ctrl_readl(TI81XX_CONTROL_MAC_ID0_LO);

                mac_hi = omap_ctrl_readl(TI81XX_CONTROL_MAC_ID0_HI);

                cpsw_slaves[0].mac_addr[0] = mac_hi & 0xFF;

                cpsw_slaves[0].mac_addr[1] = (mac_hi & 0xFF00) >> 8;

                cpsw_slaves[0].mac_addr[2] = (mac_hi & 0xFF0000) >> 16;

                cpsw_slaves[0].mac_addr[3] = (mac_hi & 0xFF000000) >> 24;

                cpsw_slaves[0].mac_addr[4] = mac_lo & 0xFF;

                cpsw_slaves[0].mac_addr[5] = (mac_lo & 0xFF00) >> 8;

 

                mac_lo = omap_ctrl_readl(TI81XX_CONTROL_MAC_ID1_LO);

                mac_hi = omap_ctrl_readl(TI81XX_CONTROL_MAC_ID1_HI);

                cpsw_slaves[1].mac_addr[0] = mac_hi & 0xFF;

                cpsw_slaves[1].mac_addr[1] = (mac_hi & 0xFF00) >> 8;

                cpsw_slaves[1].mac_addr[2] = (mac_hi & 0xFF0000) >> 16;

                cpsw_slaves[1].mac_addr[3] = (mac_hi & 0xFF000000) >> 24;

                cpsw_slaves[1].mac_addr[4] = mac_lo & 0xFF;

                cpsw_slaves[1].mac_addr[5] = (mac_lo & 0xFF00) >> 8;

#if 0

                ti814x_cpsw_mux();

#endif

                if (omap_rev() == TI8148_REV_ES1_0)

                                cpsw_slaves[0].phy_id = "0:01";

                else {

                                cpsw_slaves[0].phy_id = "0:00";

                                cpsw_slaves[1].phy_id = "0:01";

                }

 

                platform_device_register(&cpsw_mdio_device);

                platform_device_register(&ti814x_cpsw_device);

                clk_add_alias(NULL, dev_name(&cpsw_mdio_device.dev),

                                                NULL, &ti814x_cpsw_device.dev);

}

#else

static inline void ti814x_cpsw_init(void) {}

#endif

 

void ti814x_cpsw_mux(void)

{

#if 0 /* No pinmux for now */

                omap_mux_init_signal("gmii1_rxclk", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_rxd0", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_rxd1", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_rxd2", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_rxd3", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_rxd4", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_rxd5", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_rxd6", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_rxd7", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_rxdv", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_gtxclk", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_txd0", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_txd1", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_txd2", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_txd3", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_txd4", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_txd5", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_txd6", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_txd7", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_txen", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_txclk", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_col", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_crs", OMAP_MUX_MODE1);

                omap_mux_init_signal("gmii1_rxer", OMAP_MUX_MODE1);

#endif

}

 

Now in docs section of TI814X-LINUX-PSP-04.01.00.05, in DM814x C6A814x AM387x PSP User Guide

under the section its told that

 

Modifying Pin Mux settings

=====================

On DM814x devices, the pins are tri-stated and set to Mode 0 or any other mode as required for specific module

(e.g., MMC) in U-Boot. If you desire to use a particular pin to any other function than Mode 0 or override any other

pin mode which was already set in U-Boot, the kernel needs to be modified and rebuilt.

 

You can change default mux mode by adding specific mux entry in the beginning of board_mux array in

arch/arm/mach-omap2/board-ti8148evm.c or calling omap_mux_init_signal() during

initialization (e.g., in device specific initialization function called from omap2_init_devices() in

arch/arm/mach-omap2/devices.c).

 

The names of multiplexed signals are specified in arch/arm/mach-omap2/mux814x.c file in kernel source directory.

e.g., for setting xref_clk0 pin (mode 0) to usb1_drvvbus (mode 7 or FUNCTION 8), add

TI814X_MUX(XREF_CLK0, OMAP_MUX_MODE7) to board_mux structure in board file or call

omap_mux_init_signal("xref_clk0", OMAP_MUX_MODE7)

The API approach is useful if you desire to set the pin-mux run time depending upon the board/hardware detected

without need of maintaining separate kernel binaries.

 

Note: On DM814x devices, the bit positions for pull up/down are different and hence use macros

TI814X_PULL_DIS (to disable pull up/down) or TI814X_PULL_UP to select pull up.

 

So now to make our custom board work is it enough if we give something like

omap_mux_init_signal("rmii0_rxer", OMAP_MUX_MODE2);

omap_mux_init_signal("rmii0_rxd1", OMAP_MUX_MODE2);

omap_mux_init_signal("rmii0_rxd0", OMAP_MUX_MODE2);

 

 

 

omap_mux_init_signal("rmii0_crs", OMAP_MUX_MODE2);

omap_mux_init_signal("rmii0_txd0" , OMAP_MUX_MODE2);

omap_mux_init_signal("rmii0_txd0" , OMAP_MUX_MODE2);

omap_mux_init_signal("rmii0_txen" , OMAP_MUX_MODE2);

omap_mux_init_signal("rmii_refclk" , OMAP_MUX_MODE0); in

void ti814x_cpsw_mux(void)

{

}

in as datsheet says the same.

Without doing this right now we get the error when we execute  the function davinci_mdio_reset

static void __davinci_mdio_reset(struct davinci_mdio_data *data)

{

      u32 mdio_in, div, mdio_out_khz, access_time;

 

      mdio_in = clk_get_rate(data->clk);

      div = (mdio_in / data->pdata.bus_freq) - 1;

      if (div > CONTROL_MAX_DIV)

            div = CONTROL_MAX_DIV;

 

      /* set enable and clock divider */

      __raw_writel(div | CONTROL_ENABLE, &data->regs->control);

 

      /*

       * One mdio transaction consists of:

       *    32 bits of preamble

       *    32 bits of transferred data

       *    24 bits of bus yield (not needed unless shared?)

       */

      mdio_out_khz = mdio_in / (1000 * (div + 1));

      access_time  = (88 * 1000) / mdio_out_khz;

 

      /*

       * In the worst case, we could be kicking off a user-access immediately

       * after the mdio bus scan state-machine triggered its own read.  If

       * so, our request could get deferred by one access cycle.  We

       * defensively allow for 4 access cycles.

       */

      data->access_time = usecs_to_jiffies(access_time * 4);

      if (!data->access_time)

            data->access_time = 1;

}

 

static int davinci_mdio_reset(struct mii_bus *bus)

{

      struct davinci_mdio_data *data = bus->priv;

      u32 phy_mask, ver;

 

      printk(KERN_CRIT "ETHERNET:inside the davinci_mdio_reset\n");

      __davinci_mdio_reset(data);

 

      /* wait for scan logic to settle */

      msleep(PHY_MAX_ADDR * data->access_time);

 

      /* dump hardware version info */

      ver = __raw_readl(&data->regs->version);

      dev_info(data->dev, "davinci mdio revision %d.%d\n",

             (ver >> 8) & 0xff, ver & 0xff);

 

      /* get phy mask from the alive register */

      phy_mask = __raw_readl(&data->regs->alive);

      if (phy_mask) {

            /* restrict mdio bus to live phys only */

            dev_info(data->dev, "detected phy mask %x\n", ~phy_mask);//things will go wrong here as no clock as pimuxing not done

            phy_mask = ~phy_mask;

      } else {

            /* desperately scan all phys */

            dev_warn(data->dev, "no live phy, scanning all\n");

            phy_mask = 0;

      }

      data->bus->phy_mask = phy_mask;

 

      return 0;

}

 

/* wait until hardware is ready for another user access */

static inline int wait_for_user_access(struct davinci_mdio_data *data)

{

      struct davinci_mdio_regs __iomem *regs = data->regs;

      unsigned long timeout = jiffies + msecs_to_jiffies(MDIO_TIMEOUT);

      u32 reg;

 

      while (time_after(timeout, jiffies)) {

            reg = __raw_readl(&regs->user[0].access);

            if ((reg & USERACCESS_GO) == 0)

                  return 0;

 

            reg = __raw_readl(&regs->control);

            if ((reg & CONTROL_IDLE) == 0)

                  continue;

 

            /*

             * An emac soft_reset may have clobbered the mdio controller's

             * state machine.  We need to reset and retry the current

             * operation

             */

            dev_warn(data->dev, "resetting idled controller\n");

            __davinci_mdio_reset(data);

            return -EAGAIN;

      }

      dev_err(data->dev, "timed out waiting for user access\n");

      return -ETIMEDOUT;

}

 

/* wait until hardware state machine is idle */

static inline int wait_for_idle(struct davinci_mdio_data *data)

{

      struct davinci_mdio_regs __iomem *regs = data->regs;

      unsigned long timeout = jiffies + msecs_to_jiffies(MDIO_TIMEOUT);

 

      while (time_after(timeout, jiffies)) {

            if (__raw_readl(&regs->control) & CONTROL_IDLE)

                  return 0;

      }

      dev_err(data->dev, "timed out waiting for idle\n");

      return -ETIMEDOUT;

}

 

static int davinci_mdio_read(struct mii_bus *bus, int phy_id, int phy_reg)

{

      struct davinci_mdio_data *data = bus->priv;

      u32 reg;

      int ret;

 

      if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)

            return -EINVAL;

 

      spin_lock(&data->lock);

 

      if (data->suspended) {

            spin_unlock(&data->lock);

            return -ENODEV;

      }

 

      reg = (USERACCESS_GO | USERACCESS_READ | (phy_reg << 21) |

             (phy_id << 16));

 

      while (1) {

            ret = wait_for_user_access(data);

            if (ret == -EAGAIN)

                  continue;

            if (ret < 0)

                  break;

 

            __raw_writel(reg, &data->regs->user[0].access);

 

            ret = wait_for_user_access(data);

            if (ret == -EAGAIN)

                  continue;

            if (ret < 0)

                  break;

 

            reg = __raw_readl(&data->regs->user[0].access);

            ret = (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -EIO;

            break;

      }

 

      spin_unlock(&data->lock);

 

      return ret;

}

 

static int davinci_mdio_write(struct mii_bus *bus, int phy_id,

                        int phy_reg, u16 phy_data)

{

      struct davinci_mdio_data *data = bus->priv;

      u32 reg;

      int ret;

 

      if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)

            return -EINVAL;

 

      spin_lock(&data->lock);

 

      if (data->suspended) {

            spin_unlock(&data->lock);

            return -ENODEV;

      }

 

      reg = (USERACCESS_GO | USERACCESS_WRITE | (phy_reg << 21) |

               (phy_id << 16) | (phy_data & USERACCESS_DATA));

 

      while (1) {

            ret = wait_for_user_access(data);

            if (ret == -EAGAIN)

                  continue;

            if (ret < 0)

                  break;

 

            __raw_writel(reg, &data->regs->user[0].access);

 

            ret = wait_for_user_access(data);

            if (ret == -EAGAIN)

                  continue;

            break;

      }

 

      spin_unlock(&data->lock);

 

      return 0;

}

 

static int __devinit davinci_mdio_probe(struct platform_device *pdev)

{

      struct mdio_platform_data *pdata = pdev->dev.platform_data;

      struct device *dev = &pdev->dev;

      struct davinci_mdio_data *data;

      struct resource *res;

      struct phy_device *phy;

      int ret, addr;

 

      printk(KERN_CRIT "ETHERNET:inside the davinci_mdio_probe\n");

      data = kzalloc(sizeof(*data), GFP_KERNEL);

      if (!data) {

            dev_err(dev, "failed to alloc device data\n");

            return -ENOMEM;

      }

 

      data->pdata = pdata ? (*pdata) : default_pdata;

 

      data->bus = mdiobus_alloc();

      if (!data->bus) {

            dev_err(dev, "failed to alloc mii bus\n");

            ret = -ENOMEM;

            goto bail_out;

      }

 

      data->bus->name         = dev_name(dev);

      data->bus->read         = davinci_mdio_read,

      data->bus->write  = davinci_mdio_write,

      data->bus->reset  = davinci_mdio_reset,

      data->bus->parent = dev;

      data->bus->priv         = data;

      snprintf(data->bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);

 

      data->clk = clk_get(dev, NULL);

      if (IS_ERR(data->clk)) {

            data->clk = NULL;

            dev_err(dev, "failed to get device clock\n");

//          ret = PTR_ERR(data->clk);

//          goto bail_out;

      }

      printk(KERN_CRIT "ETHERNET:inside davinci mdio_probe b4 clk_enable\n");

      clk_enable(data->clk);

      printk(KERN_CRIT "ETHERNET:inside davinci mdio_probe after clk_enable b4 dev_set_drvdata\n");

      dev_set_drvdata(dev, data);

      printk(KERN_CRIT "ETHERNET:inside davinci mdio_probe after dev_set_drvdata\n");

      data->dev = dev;

      spin_lock_init(&data->lock);

 

      printk(KERN_CRIT "ETHERNET:inside davinci mdio_probe b4 calling platform_get_resource\n");

      res = platform_get_resource(pdev, IORESOURCE_MEM, 0);

      if (!res) {

            dev_err(dev, "could not find register map resource\n");

            ret = -ENOENT;

            goto bail_out;

      }

      printk(KERN_CRIT "ETHERNET:inside davinci mdio_probe b4 calling devm_request_mem_region\n");

 

      res = devm_request_mem_region(dev, res->start, resource_size(res),

                                  dev_name(dev));

      if (!res) {

            dev_err(dev, "could not allocate register map resource\n");

            ret = -ENXIO;

            goto bail_out;

      }

 

      printk(KERN_CRIT "ETHERNET:inside davinci mdio_probe b4 calling devm_ioremap_nocache\n");

      data->regs = devm_ioremap_nocache(dev, res->start, resource_size(res));

      if (!data->regs) {

            dev_err(dev, "could not map mdio registers\n");

            ret = -ENOMEM;

            goto bail_out;

      }

 

      /* register the mii bus */

      printk(KERN_CRIT "ETHERNET:inside davinci mdio_probe b4 calling mdiobus_register\n");

      ret = mdiobus_register(data->bus); //after this davinci_mdio_reset gets called

      if (ret)

            goto bail_out;

 

      /* scan and dump the bus */

      for (addr = 0; addr < PHY_MAX_ADDR; addr++) {

            phy = data->bus->phy_map[addr];

            if (phy) {

                  dev_info(dev, "phy[%d]: device %s, driver %s\n",

                         phy->addr, dev_name(&phy->dev),

                         phy->drv ? phy->drv->name : "unknown");

            }

      }

 

      return 0;

 

bail_out:

      if (data->bus)

            mdiobus_free(data->bus);

 

      if (data->clk) {

            clk_disable(data->clk);

            clk_put(data->clk);

      }

 

      kfree(data);

 

      return ret;

}

 

static int __devexit davinci_mdio_remove(struct platform_device *pdev)

{

      struct device *dev = &pdev->dev;

      struct davinci_mdio_data *data = dev_get_drvdata(dev);

 

      if (data->bus)

            mdiobus_free(data->bus);

 

      if (data->clk) {

            clk_disable(data->clk);

            clk_put(data->clk);

      }

 

      dev_set_drvdata(dev, NULL);

 

      kfree(data);

 

      return 0;

}

 

static int davinci_mdio_suspend(struct device *dev)

{

      struct davinci_mdio_data *data = dev_get_drvdata(dev);

      u32 ctrl;

 

      spin_lock(&data->lock);

 

      /* shutdown the scan state machine */

      ctrl = __raw_readl(&data->regs->control);

      ctrl &= ~CONTROL_ENABLE;

      __raw_writel(ctrl, &data->regs->control);

      wait_for_idle(data);

 

      if (data->clk)

            clk_disable(data->clk);

 

      data->suspended = true;

      spin_unlock(&data->lock);

 

      return 0;

}

 

static int davinci_mdio_resume(struct device *dev)

{

      struct davinci_mdio_data *data = dev_get_drvdata(dev);

      u32 ctrl;

 

      spin_lock(&data->lock);

      if (data->clk)

            clk_enable(data->clk);

 

      /* restart the scan state machine */

      ctrl = __raw_readl(&data->regs->control);

      ctrl |= CONTROL_ENABLE;

      __raw_writel(ctrl, &data->regs->control);

 

      data->suspended = false;

      spin_unlock(&data->lock);

 

      return 0;

}

 

static const struct dev_pm_ops davinci_mdio_pm_ops = {

      .suspend    = davinci_mdio_suspend,

      .resume           = davinci_mdio_resume,

};

 

static struct platform_driver davinci_mdio_driver = {

      .driver = {

            .name = "davinci_mdio",

            .owner      = THIS_MODULE,

            .pm   = &davinci_mdio_pm_ops,

      },

      .probe = davinci_mdio_probe,

      .remove = __devexit_p(davinci_mdio_remove),

};

 

static int __init davinci_mdio_init(void)

{

      return platform_driver_register(&davinci_mdio_driver);

}

device_initcall(davinci_mdio_init);

 

static void __exit davinci_mdio_exit(void)

{

      platform_driver_unregister(&davinci_mdio_driver);

}

module_exit(davinci_mdio_exit);

 

MODULE_LICENSE("GPL");

MODULE_DESCRIPTION("DaVinci MDIO driver");

 

 

 

 

 So adding just the pinmuxing will it do for phy to be recognised and start working in RMII mode.

or more has to be done like at

static struct cpsw_platform_data ti814x_cpsw_pdata = {
 .ss_reg_ofs  = 0x900,
 .channels  = 8,
 .cpdma_reg_ofs  = 0x100,
 .slaves   = 1,
 .slave_data  = cpsw_slaves,
 .ale_reg_ofs  = 0x600,
 .ale_entries  = 1024,
 .host_port_reg_ofs      = 0x28,
 .hw_stats_reg_ofs       = 0x400,
 .bd_ram_ofs  = 0x2000,
 .bd_ram_size  = SZ_8K,
 .rx_descs               = 64,
 .mac_control            = BIT(5), /* MIIEN */
 .gigabit_en  = 1,
 .host_port_num  = 0,
 .no_bd_ram  = false,
};

Thanks and Regards,

-P

 

 

 

 

  • Pradeep

    By configuring pin-mux will do to recognise and work in RMII mode.

    --

    Mugunthan V N

  • in arch/arm/mach-omap2/devices.c

    • following function has to be implemented to make CPSW pin mux to RMII
    • in ti814x_cpsw_init(), ti814x_cpsw_mux() has to called to enable pin muxing.

    void ti814x_cpsw_mux(void)
    {
        /* RMII Ref clock */
        omap_mux_init_signal("rmii_refclk" , OMAP_MUX_MODE0);

        /* Port 1 */
        omap_mux_init_signal("rmii0_rxer", OMAP_MUX_MODE2);
        omap_mux_init_signal("rmii0_rxd1", OMAP_MUX_MODE2);
        omap_mux_init_signal("rmii0_rxd0", OMAP_MUX_MODE2);
        omap_mux_init_signal("rmii0_crs", OMAP_MUX_MODE2);
        omap_mux_init_signal("rmii0_txd0" , OMAP_MUX_MODE2);
        omap_mux_init_signal("rmii0_txd0" , OMAP_MUX_MODE2);
        omap_mux_init_signal("rmii0_txen" , OMAP_MUX_MODE2);

        /* Port 2 */
        omap_mux_init_signal("rmii1_rxer", OMAP_MUX_MODE1);
        omap_mux_init_signal("rmii1_rxd1", OMAP_MUX_MODE1);
        omap_mux_init_signal("rmii1_rxd0", OMAP_MUX_MODE1);
        omap_mux_init_signal("rmii1_crs", OMAP_MUX_MODE1);
        omap_mux_init_signal("rmii1_txd0" , OMAP_MUX_MODE1);
        omap_mux_init_signal("rmii1_txd0" , OMAP_MUX_MODE1);
        omap_mux_init_signal("rmii1_txen" , OMAP_MUX_MODE1);
    }

    If this solves your query, please mark it as answered.

     

    with regards

    Mugunthan V N

  • Pradeep

    Add below patch to make the gasket to RMII mode

    diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
    index a0612c4..890c0f3 100644
    --- a/arch/arm/mach-omap2/control.h
    +++ b/arch/arm/mach-omap2/control.h
    @@ -266,6 +266,7 @@
     #define TI81XX_CONTROL_MAC_ID1_LO      (TI81XX_CONTROL_DEVCONF + 0x038)
     #define TI81XX_CONTROL_MAC_ID1_HI      (TI81XX_CONTROL_DEVCONF + 0x03c)
     #define TI816X_CONTROL_PCIE_CFG                (TI81XX_CONTROL_DEVCONF + 0x040)
    +#define TI814X_CONTROL_MAC_MII_SEL     (TI81XX_CONTROL_DEVCONF + 0x050)
     #define TI814X_CONTROL_PCIE_PLLCFG0    (TI81XX_CONTROL_DEVCONF + 0x0D8)
     #define TI814X_CONTROL_PCIE_PLLCFG1    (TI81XX_CONTROL_DEVCONF + 0x0DC)
     #define TI814X_CONTROL_PCIE_PLLCFG2    (TI81XX_CONTROL_DEVCONF + 0x0E0)

    and init MII_SEL register to select RMII mode in ti814x_cpsw_mux()

    omap_ctrl_writel(0x5, TI814X_CONTROL_MAC_MII_SEL);


    with regards

    Mugunthan V N

  • Hi Mugunthan VN,

    Thanks for your reply, dear friend myself was busy in making the RMII mode work at U-boot level and now able to ping from board to host

    so now working at kernel to have NFS for our custom board.

    About your code

    =============

    We use only one so the code should be

    void ti814x_cpsw_mux(void)
    {
        /* RMII Ref clock */
        omap_mux_init_signal("rmii_refclk" , OMAP_MUX_MODE0);

        /* Port 1 */
        omap_mux_init_signal("rmii0_rxer", OMAP_MUX_MODE2);
        omap_mux_init_signal("rmii0_rxd1", OMAP_MUX_MODE2);
        omap_mux_init_signal("rmii0_rxd0", OMAP_MUX_MODE2);
        omap_mux_init_signal("rmii0_crs", OMAP_MUX_MODE2);
        omap_mux_init_signal("rmii0_txd0" , OMAP_MUX_MODE2);
        omap_mux_init_signal("rmii0_txd0" , OMAP_MUX_MODE2);
        omap_mux_init_signal("rmii0_txen" , OMAP_MUX_MODE2);

    }

    If had used two then

    it should have been like

    void ti814x_cpsw_mux(void)
    {
        /* RMII Ref clock */
        omap_mux_init_signal("rmii_refclk" , OMAP_MUX_MODE0);

        /* Port 1 */
        omap_mux_init_signal("rmii0_rxer", OMAP_MUX_MODE2);
        omap_mux_init_signal("rmii0_rxd1", OMAP_MUX_MODE2);
        omap_mux_init_signal("rmii0_rxd0", OMAP_MUX_MODE2);
        omap_mux_init_signal("rmii0_crs", OMAP_MUX_MODE2);
        omap_mux_init_signal("rmii0_txd0" , OMAP_MUX_MODE2);
        omap_mux_init_signal("rmii0_txd0" , OMAP_MUX_MODE2);
        omap_mux_init_signal("rmii0_txen" , OMAP_MUX_MODE2);

        /* Port 2 */
        omap_mux_init_signal("rmii1_rxer", OMAP_MUX_MODE1);
        omap_mux_init_signal("rmii1_rxd1", OMAP_MUX_MODE1);
        omap_mux_init_signal("rmii1_rxd0", OMAP_MUX_MODE1);
        omap_mux_init_signal("rmii1_crs", OMAP_MUX_MODE1);
        omap_mux_init_signal("rmii1_txd0" , OMAP_MUX_MODE1);
        omap_mux_init_signal("rmii1_txd0" , OMAP_MUX_MODE1);
        omap_mux_init_signal("rmii1_txen" , OMAP_MUX_MODE1);
    }

    Anyways thanks a lot for your reply and re-assuring.

     

    --With best Wishes,

    P

  • Pradeep,

    If you have only one instance then initializing that particular port is enough.

    with regards

    Mugunthan V N