uboot/drivers/net/pic32_eth.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (c) 2015 Purna Chandra Mandal <purna.mandal@microchip.com>
   4 *
   5 */
   6#include <common.h>
   7#include <errno.h>
   8#include <dm.h>
   9#include <net.h>
  10#include <miiphy.h>
  11#include <console.h>
  12#include <wait_bit.h>
  13#include <asm/gpio.h>
  14
  15#include "pic32_eth.h"
  16
  17#define MAX_RX_BUF_SIZE         1536
  18#define MAX_RX_DESCR            PKTBUFSRX
  19#define MAX_TX_DESCR            2
  20
  21DECLARE_GLOBAL_DATA_PTR;
  22
  23struct pic32eth_dev {
  24        struct eth_dma_desc rxd_ring[MAX_RX_DESCR];
  25        struct eth_dma_desc txd_ring[MAX_TX_DESCR];
  26        u32 rxd_idx; /* index of RX desc to read */
  27        /* regs */
  28        struct pic32_ectl_regs *ectl_regs;
  29        struct pic32_emac_regs *emac_regs;
  30        /* Phy */
  31        struct phy_device *phydev;
  32        phy_interface_t phyif;
  33        u32 phy_addr;
  34        struct gpio_desc rst_gpio;
  35};
  36
  37void __weak board_netphy_reset(void *dev)
  38{
  39        struct pic32eth_dev *priv = dev;
  40
  41        if (!dm_gpio_is_valid(&priv->rst_gpio))
  42                return;
  43
  44        /* phy reset */
  45        dm_gpio_set_value(&priv->rst_gpio, 0);
  46        udelay(300);
  47        dm_gpio_set_value(&priv->rst_gpio, 1);
  48        udelay(300);
  49}
  50
  51/* Initialize mii(MDIO) interface, discover which PHY is
  52 * attached to the device, and configure it properly.
  53 */
  54static int pic32_mii_init(struct pic32eth_dev *priv)
  55{
  56        struct pic32_ectl_regs *ectl_p = priv->ectl_regs;
  57        struct pic32_emac_regs *emac_p = priv->emac_regs;
  58
  59        /* board phy reset */
  60        board_netphy_reset(priv);
  61
  62        /* disable RX, TX & all transactions */
  63        writel(ETHCON_ON | ETHCON_TXRTS | ETHCON_RXEN, &ectl_p->con1.clr);
  64
  65        /* wait till busy */
  66        wait_for_bit_le32(&ectl_p->stat.raw, ETHSTAT_BUSY, false,
  67                          CONFIG_SYS_HZ, false);
  68
  69        /* turn controller ON to access PHY over MII */
  70        writel(ETHCON_ON, &ectl_p->con1.set);
  71
  72        mdelay(10);
  73
  74        /* reset MAC */
  75        writel(EMAC_SOFTRESET, &emac_p->cfg1.set); /* reset assert */
  76        mdelay(10);
  77        writel(EMAC_SOFTRESET, &emac_p->cfg1.clr); /* reset deassert */
  78
  79        /* initialize MDIO/MII */
  80        if (priv->phyif == PHY_INTERFACE_MODE_RMII) {
  81                writel(EMAC_RMII_RESET, &emac_p->supp.set);
  82                mdelay(10);
  83                writel(EMAC_RMII_RESET, &emac_p->supp.clr);
  84        }
  85
  86        return pic32_mdio_init(PIC32_MDIO_NAME, (ulong)&emac_p->mii);
  87}
  88
  89static int pic32_phy_init(struct pic32eth_dev *priv, struct udevice *dev)
  90{
  91        struct mii_dev *mii;
  92
  93        mii = miiphy_get_dev_by_name(PIC32_MDIO_NAME);
  94
  95        /* find & connect PHY */
  96        priv->phydev = phy_connect(mii, priv->phy_addr,
  97                                   dev, priv->phyif);
  98        if (!priv->phydev) {
  99                printf("%s: %s: Error, PHY connect\n", __FILE__, __func__);
 100                return 0;
 101        }
 102
 103        /* Wait for phy to complete reset */
 104        mdelay(10);
 105
 106        /* configure supported modes */
 107        priv->phydev->supported = SUPPORTED_10baseT_Half |
 108                                  SUPPORTED_10baseT_Full |
 109                                  SUPPORTED_100baseT_Half |
 110                                  SUPPORTED_100baseT_Full |
 111                                  SUPPORTED_Autoneg;
 112
 113        priv->phydev->advertising = ADVERTISED_10baseT_Half |
 114                                    ADVERTISED_10baseT_Full |
 115                                    ADVERTISED_100baseT_Half |
 116                                    ADVERTISED_100baseT_Full |
 117                                    ADVERTISED_Autoneg;
 118
 119        priv->phydev->autoneg = AUTONEG_ENABLE;
 120
 121        return 0;
 122}
 123
 124/* Configure MAC based on negotiated speed and duplex
 125 * reported by PHY.
 126 */
 127static int pic32_mac_adjust_link(struct pic32eth_dev *priv)
 128{
 129        struct phy_device *phydev = priv->phydev;
 130        struct pic32_emac_regs *emac_p = priv->emac_regs;
 131
 132        if (!phydev->link) {
 133                printf("%s: No link.\n", phydev->dev->name);
 134                return -EINVAL;
 135        }
 136
 137        if (phydev->duplex) {
 138                writel(EMAC_FULLDUP, &emac_p->cfg2.set);
 139                writel(FULLDUP_GAP_TIME, &emac_p->ipgt.raw);
 140        } else {
 141                writel(EMAC_FULLDUP, &emac_p->cfg2.clr);
 142                writel(HALFDUP_GAP_TIME, &emac_p->ipgt.raw);
 143        }
 144
 145        switch (phydev->speed) {
 146        case SPEED_100:
 147                writel(EMAC_RMII_SPD100, &emac_p->supp.set);
 148                break;
 149        case SPEED_10:
 150                writel(EMAC_RMII_SPD100, &emac_p->supp.clr);
 151                break;
 152        default:
 153                printf("%s: Speed was bad\n", phydev->dev->name);
 154                return -EINVAL;
 155        }
 156
 157        printf("pic32eth: PHY is %s with %dbase%s, %s\n",
 158               phydev->drv->name, phydev->speed,
 159               (phydev->port == PORT_TP) ? "T" : "X",
 160               (phydev->duplex) ? "full" : "half");
 161
 162        return 0;
 163}
 164
 165static void pic32_mac_init(struct pic32eth_dev *priv, u8 *macaddr)
 166{
 167        struct pic32_emac_regs *emac_p = priv->emac_regs;
 168        u32 stat = 0, v;
 169        u64 expire;
 170
 171        v = EMAC_TXPAUSE | EMAC_RXPAUSE | EMAC_RXENABLE;
 172        writel(v, &emac_p->cfg1.raw);
 173
 174        v = EMAC_EXCESS | EMAC_AUTOPAD | EMAC_PADENABLE |
 175            EMAC_CRCENABLE | EMAC_LENGTHCK | EMAC_FULLDUP;
 176        writel(v, &emac_p->cfg2.raw);
 177
 178        /* recommended back-to-back inter-packet gap for 10 Mbps half duplex */
 179        writel(HALFDUP_GAP_TIME, &emac_p->ipgt.raw);
 180
 181        /* recommended non-back-to-back interpacket gap is 0xc12 */
 182        writel(0xc12, &emac_p->ipgr.raw);
 183
 184        /* recommended collision window retry limit is 0x370F */
 185        writel(0x370f, &emac_p->clrt.raw);
 186
 187        /* set maximum frame length: allow VLAN tagged frame */
 188        writel(0x600, &emac_p->maxf.raw);
 189
 190        /* set the mac address */
 191        writel(macaddr[0] | (macaddr[1] << 8), &emac_p->sa2.raw);
 192        writel(macaddr[2] | (macaddr[3] << 8), &emac_p->sa1.raw);
 193        writel(macaddr[4] | (macaddr[5] << 8), &emac_p->sa0.raw);
 194
 195        /* default, enable 10 Mbps operation */
 196        writel(EMAC_RMII_SPD100, &emac_p->supp.clr);
 197
 198        /* wait until link status UP or deadline elapsed */
 199        expire = get_ticks() + get_tbclk() * 2;
 200        for (; get_ticks() < expire;) {
 201                stat = phy_read(priv->phydev, priv->phy_addr, MII_BMSR);
 202                if (stat & BMSR_LSTATUS)
 203                        break;
 204        }
 205
 206        if (!(stat & BMSR_LSTATUS))
 207                printf("MAC: Link is DOWN!\n");
 208
 209        /* delay to stabilize before any tx/rx */
 210        mdelay(10);
 211}
 212
 213static void pic32_mac_reset(struct pic32eth_dev *priv)
 214{
 215        struct pic32_emac_regs *emac_p = priv->emac_regs;
 216        struct mii_dev *mii;
 217
 218        /* Reset MAC */
 219        writel(EMAC_SOFTRESET, &emac_p->cfg1.raw);
 220        mdelay(10);
 221
 222        /* clear reset */
 223        writel(0, &emac_p->cfg1.raw);
 224
 225        /* Reset MII */
 226        mii = priv->phydev->bus;
 227        if (mii && mii->reset)
 228                mii->reset(mii);
 229}
 230
 231/* initializes the MAC and PHY, then establishes a link */
 232static void pic32_ctrl_reset(struct pic32eth_dev *priv)
 233{
 234        struct pic32_ectl_regs *ectl_p = priv->ectl_regs;
 235        u32 v;
 236
 237        /* disable RX, TX & any other transactions */
 238        writel(ETHCON_ON | ETHCON_TXRTS | ETHCON_RXEN, &ectl_p->con1.clr);
 239
 240        /* wait till busy */
 241        wait_for_bit_le32(&ectl_p->stat.raw, ETHSTAT_BUSY, false,
 242                          CONFIG_SYS_HZ, false);
 243        /* decrement received buffcnt to zero. */
 244        while (readl(&ectl_p->stat.raw) & ETHSTAT_BUFCNT)
 245                writel(ETHCON_BUFCDEC, &ectl_p->con1.set);
 246
 247        /* clear any existing interrupt event */
 248        writel(0xffffffff, &ectl_p->irq.clr);
 249
 250        /* clear RX/TX start address */
 251        writel(0xffffffff, &ectl_p->txst.clr);
 252        writel(0xffffffff, &ectl_p->rxst.clr);
 253
 254        /* clear the receive filters */
 255        writel(0x00ff, &ectl_p->rxfc.clr);
 256
 257        /* set the receive filters
 258         * ETH_FILT_CRC_ERR_REJECT
 259         * ETH_FILT_RUNT_REJECT
 260         * ETH_FILT_UCAST_ACCEPT
 261         * ETH_FILT_MCAST_ACCEPT
 262         * ETH_FILT_BCAST_ACCEPT
 263         */
 264        v = ETHRXFC_BCEN | ETHRXFC_MCEN | ETHRXFC_UCEN |
 265            ETHRXFC_RUNTEN | ETHRXFC_CRCOKEN;
 266        writel(v, &ectl_p->rxfc.set);
 267
 268        /* turn controller ON to access PHY over MII */
 269        writel(ETHCON_ON, &ectl_p->con1.set);
 270}
 271
 272static void pic32_rx_desc_init(struct pic32eth_dev *priv)
 273{
 274        struct pic32_ectl_regs *ectl_p = priv->ectl_regs;
 275        struct eth_dma_desc *rxd;
 276        u32 idx, bufsz;
 277
 278        priv->rxd_idx = 0;
 279        for (idx = 0; idx < MAX_RX_DESCR; idx++) {
 280                rxd = &priv->rxd_ring[idx];
 281
 282                /* hw owned */
 283                rxd->hdr = EDH_NPV | EDH_EOWN | EDH_STICKY;
 284
 285                /* packet buffer address */
 286                rxd->data_buff = virt_to_phys(net_rx_packets[idx]);
 287
 288                /* link to next desc */
 289                rxd->next_ed = virt_to_phys(rxd + 1);
 290
 291                /* reset status */
 292                rxd->stat1 = 0;
 293                rxd->stat2 = 0;
 294
 295                /* decrement bufcnt */
 296                writel(ETHCON_BUFCDEC, &ectl_p->con1.set);
 297        }
 298
 299        /* link last descr to beginning of list */
 300        rxd->next_ed = virt_to_phys(&priv->rxd_ring[0]);
 301
 302        /* flush rx ring */
 303        flush_dcache_range((ulong)priv->rxd_ring,
 304                           (ulong)priv->rxd_ring + sizeof(priv->rxd_ring));
 305
 306        /* set rx desc-ring start address */
 307        writel((ulong)virt_to_phys(&priv->rxd_ring[0]), &ectl_p->rxst.raw);
 308
 309        /* RX Buffer size */
 310        bufsz = readl(&ectl_p->con2.raw);
 311        bufsz &= ~(ETHCON_RXBUFSZ << ETHCON_RXBUFSZ_SHFT);
 312        bufsz |= ((MAX_RX_BUF_SIZE / 16) << ETHCON_RXBUFSZ_SHFT);
 313        writel(bufsz, &ectl_p->con2.raw);
 314
 315        /* enable the receiver in hardware which allows hardware
 316         * to DMA received pkts to the descriptor pointer address.
 317         */
 318        writel(ETHCON_RXEN, &ectl_p->con1.set);
 319}
 320
 321static int pic32_eth_start(struct udevice *dev)
 322{
 323        struct eth_pdata *pdata = dev_get_platdata(dev);
 324        struct pic32eth_dev *priv = dev_get_priv(dev);
 325
 326        /* controller */
 327        pic32_ctrl_reset(priv);
 328
 329        /* reset MAC */
 330        pic32_mac_reset(priv);
 331
 332        /* configure PHY */
 333        phy_config(priv->phydev);
 334
 335        /* initialize MAC */
 336        pic32_mac_init(priv, &pdata->enetaddr[0]);
 337
 338        /* init RX descriptor; TX descriptors are handled in xmit */
 339        pic32_rx_desc_init(priv);
 340
 341        /* Start up & update link status of PHY */
 342        phy_startup(priv->phydev);
 343
 344        /* adjust mac with phy link status */
 345        return pic32_mac_adjust_link(priv);
 346}
 347
 348static void pic32_eth_stop(struct udevice *dev)
 349{
 350        struct pic32eth_dev *priv = dev_get_priv(dev);
 351        struct pic32_ectl_regs *ectl_p = priv->ectl_regs;
 352        struct pic32_emac_regs *emac_p = priv->emac_regs;
 353
 354        /* Reset the phy if the controller is enabled */
 355        if (readl(&ectl_p->con1.raw) & ETHCON_ON)
 356                phy_reset(priv->phydev);
 357
 358        /* Shut down the PHY */
 359        phy_shutdown(priv->phydev);
 360
 361        /* Stop rx/tx */
 362        writel(ETHCON_TXRTS | ETHCON_RXEN, &ectl_p->con1.clr);
 363        mdelay(10);
 364
 365        /* reset MAC */
 366        writel(EMAC_SOFTRESET, &emac_p->cfg1.raw);
 367
 368        /* clear reset */
 369        writel(0, &emac_p->cfg1.raw);
 370        mdelay(10);
 371
 372        /* disable controller */
 373        writel(ETHCON_ON, &ectl_p->con1.clr);
 374        mdelay(10);
 375
 376        /* wait until everything is down */
 377        wait_for_bit_le32(&ectl_p->stat.raw, ETHSTAT_BUSY, false,
 378                          2 * CONFIG_SYS_HZ, false);
 379
 380        /* clear any existing interrupt event */
 381        writel(0xffffffff, &ectl_p->irq.clr);
 382}
 383
 384static int pic32_eth_send(struct udevice *dev, void *packet, int length)
 385{
 386        struct pic32eth_dev *priv = dev_get_priv(dev);
 387        struct pic32_ectl_regs *ectl_p = priv->ectl_regs;
 388        struct eth_dma_desc *txd;
 389        u64 deadline;
 390
 391        txd = &priv->txd_ring[0];
 392
 393        /* set proper flags & length in descriptor header */
 394        txd->hdr = EDH_SOP | EDH_EOP | EDH_EOWN | EDH_BCOUNT(length);
 395
 396        /* pass buffer address to hardware */
 397        txd->data_buff = virt_to_phys(packet);
 398
 399        debug("%s: %d / .hdr %x, .data_buff %x, .stat %x, .nexted %x\n",
 400              __func__, __LINE__, txd->hdr, txd->data_buff, txd->stat2,
 401              txd->next_ed);
 402
 403        /* cache flush (packet) */
 404        flush_dcache_range((ulong)packet, (ulong)packet + length);
 405
 406        /* cache flush (txd) */
 407        flush_dcache_range((ulong)txd, (ulong)txd + sizeof(*txd));
 408
 409        /* pass descriptor table base to h/w */
 410        writel(virt_to_phys(txd), &ectl_p->txst.raw);
 411
 412        /* ready to send enabled, hardware can now send the packet(s) */
 413        writel(ETHCON_TXRTS | ETHCON_ON, &ectl_p->con1.set);
 414
 415        /* wait until tx has completed and h/w has released ownership
 416         * of the tx descriptor or timeout elapsed.
 417         */
 418        deadline = get_ticks() + get_tbclk();
 419        for (;;) {
 420                /* check timeout */
 421                if (get_ticks() > deadline)
 422                        return -ETIMEDOUT;
 423
 424                if (ctrlc())
 425                        return -EINTR;
 426
 427                /* tx completed ? */
 428                if (readl(&ectl_p->con1.raw) & ETHCON_TXRTS) {
 429                        udelay(1);
 430                        continue;
 431                }
 432
 433                /* h/w not released ownership yet? */
 434                invalidate_dcache_range((ulong)txd, (ulong)txd + sizeof(*txd));
 435                if (!(txd->hdr & EDH_EOWN))
 436                        break;
 437        }
 438
 439        return 0;
 440}
 441
 442static int pic32_eth_recv(struct udevice *dev, int flags, uchar **packetp)
 443{
 444        struct pic32eth_dev *priv = dev_get_priv(dev);
 445        struct eth_dma_desc *rxd;
 446        u32 idx = priv->rxd_idx;
 447        u32 rx_count;
 448
 449        /* find the next ready to receive */
 450        rxd = &priv->rxd_ring[idx];
 451
 452        invalidate_dcache_range((ulong)rxd, (ulong)rxd + sizeof(*rxd));
 453        /* check if owned by MAC */
 454        if (rxd->hdr & EDH_EOWN)
 455                return -EAGAIN;
 456
 457        /* Sanity check on header: SOP and EOP  */
 458        if ((rxd->hdr & (EDH_SOP | EDH_EOP)) != (EDH_SOP | EDH_EOP)) {
 459                printf("%s: %s, rx pkt across multiple descr\n",
 460                       __FILE__, __func__);
 461                return 0;
 462        }
 463
 464        debug("%s: %d /idx %i, hdr=%x, data_buff %x, stat %x, nexted %x\n",
 465              __func__, __LINE__, idx, rxd->hdr,
 466              rxd->data_buff, rxd->stat2, rxd->next_ed);
 467
 468        /* Sanity check on rx_stat: OK, CRC */
 469        if (!RSV_RX_OK(rxd->stat2) || RSV_CRC_ERR(rxd->stat2)) {
 470                debug("%s: %s: Error, rx problem detected\n",
 471                      __FILE__, __func__);
 472                return 0;
 473        }
 474
 475        /* invalidate dcache */
 476        rx_count = RSV_RX_COUNT(rxd->stat2);
 477        invalidate_dcache_range((ulong)net_rx_packets[idx],
 478                                (ulong)net_rx_packets[idx] + rx_count);
 479
 480        /* Pass the packet to protocol layer */
 481        *packetp = net_rx_packets[idx];
 482
 483        /* increment number of bytes rcvd (ignore CRC) */
 484        return rx_count - 4;
 485}
 486
 487static int pic32_eth_free_pkt(struct udevice *dev, uchar *packet, int length)
 488{
 489        struct pic32eth_dev *priv = dev_get_priv(dev);
 490        struct pic32_ectl_regs *ectl_p = priv->ectl_regs;
 491        struct eth_dma_desc *rxd;
 492        int idx = priv->rxd_idx;
 493
 494        /* sanity check */
 495        if (packet != net_rx_packets[idx]) {
 496                printf("rxd_id %d: packet is not matched,\n", idx);
 497                return -EAGAIN;
 498        }
 499
 500        /* prepare for receive */
 501        rxd = &priv->rxd_ring[idx];
 502        rxd->hdr = EDH_STICKY | EDH_NPV | EDH_EOWN;
 503
 504        flush_dcache_range((ulong)rxd, (ulong)rxd + sizeof(*rxd));
 505
 506        /* decrement rx pkt count */
 507        writel(ETHCON_BUFCDEC, &ectl_p->con1.set);
 508
 509        debug("%s: %d / idx %i, hdr %x, data_buff %x, stat %x, nexted %x\n",
 510              __func__, __LINE__, idx, rxd->hdr, rxd->data_buff,
 511              rxd->stat2, rxd->next_ed);
 512
 513        priv->rxd_idx = (priv->rxd_idx + 1) % MAX_RX_DESCR;
 514
 515        return 0;
 516}
 517
 518static const struct eth_ops pic32_eth_ops = {
 519        .start          = pic32_eth_start,
 520        .send           = pic32_eth_send,
 521        .recv           = pic32_eth_recv,
 522        .free_pkt       = pic32_eth_free_pkt,
 523        .stop           = pic32_eth_stop,
 524};
 525
 526static int pic32_eth_probe(struct udevice *dev)
 527{
 528        struct eth_pdata *pdata = dev_get_platdata(dev);
 529        struct pic32eth_dev *priv = dev_get_priv(dev);
 530        const char *phy_mode;
 531        void __iomem *iobase;
 532        fdt_addr_t addr;
 533        fdt_size_t size;
 534        int offset = 0;
 535        int phy_addr = -1;
 536
 537        addr = fdtdec_get_addr_size(gd->fdt_blob, dev_of_offset(dev), "reg",
 538                                    &size);
 539        if (addr == FDT_ADDR_T_NONE)
 540                return -EINVAL;
 541
 542        iobase = ioremap(addr, size);
 543        pdata->iobase = (phys_addr_t)addr;
 544
 545        /* get phy mode */
 546        pdata->phy_interface = -1;
 547        phy_mode = fdt_getprop(gd->fdt_blob, dev_of_offset(dev), "phy-mode",
 548                               NULL);
 549        if (phy_mode)
 550                pdata->phy_interface = phy_get_interface_by_name(phy_mode);
 551        if (pdata->phy_interface == -1) {
 552                debug("%s: Invalid PHY interface '%s'\n", __func__, phy_mode);
 553                return -EINVAL;
 554        }
 555
 556        /* get phy addr */
 557        offset = fdtdec_lookup_phandle(gd->fdt_blob, dev_of_offset(dev),
 558                                       "phy-handle");
 559        if (offset > 0)
 560                phy_addr = fdtdec_get_int(gd->fdt_blob, offset, "reg", -1);
 561
 562        /* phy reset gpio */
 563        gpio_request_by_name_nodev(dev_ofnode(dev), "reset-gpios", 0,
 564                                   &priv->rst_gpio, GPIOD_IS_OUT);
 565
 566        priv->phyif     = pdata->phy_interface;
 567        priv->phy_addr  = phy_addr;
 568        priv->ectl_regs = iobase;
 569        priv->emac_regs = iobase + PIC32_EMAC1CFG1;
 570
 571        pic32_mii_init(priv);
 572
 573        return pic32_phy_init(priv, dev);
 574}
 575
 576static int pic32_eth_remove(struct udevice *dev)
 577{
 578        struct pic32eth_dev *priv = dev_get_priv(dev);
 579        struct mii_dev *bus;
 580
 581        dm_gpio_free(dev, &priv->rst_gpio);
 582        phy_shutdown(priv->phydev);
 583        free(priv->phydev);
 584        bus = miiphy_get_dev_by_name(PIC32_MDIO_NAME);
 585        mdio_unregister(bus);
 586        mdio_free(bus);
 587        iounmap(priv->ectl_regs);
 588        return 0;
 589}
 590
 591static const struct udevice_id pic32_eth_ids[] = {
 592        { .compatible = "microchip,pic32mzda-eth" },
 593        { }
 594};
 595
 596U_BOOT_DRIVER(pic32_ethernet) = {
 597        .name                   = "pic32_ethernet",
 598        .id                     = UCLASS_ETH,
 599        .of_match               = pic32_eth_ids,
 600        .probe                  = pic32_eth_probe,
 601        .remove                 = pic32_eth_remove,
 602        .ops                    = &pic32_eth_ops,
 603        .priv_auto_alloc_size   = sizeof(struct pic32eth_dev),
 604        .platdata_auto_alloc_size       = sizeof(struct eth_pdata),
 605};
 606