linux/drivers/mtd/nand/jz4740_nand.c
<<
>>
Prefs
   1/*
   2 *  Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
   3 *  JZ4740 SoC NAND controller driver
   4 *
   5 *  This program is free software; you can redistribute it and/or modify it
   6 *  under  the terms of the GNU General  Public License as published by the
   7 *  Free Software Foundation;  either version 2 of the License, or (at your
   8 *  option) any later version.
   9 *
  10 *  You should have received a copy of the GNU General Public License along
  11 *  with this program; if not, write to the Free Software Foundation, Inc.,
  12 *  675 Mass Ave, Cambridge, MA 02139, USA.
  13 *
  14 */
  15
  16#include <linux/ioport.h>
  17#include <linux/kernel.h>
  18#include <linux/module.h>
  19#include <linux/platform_device.h>
  20#include <linux/slab.h>
  21
  22#include <linux/mtd/mtd.h>
  23#include <linux/mtd/nand.h>
  24#include <linux/mtd/partitions.h>
  25
  26#include <linux/gpio.h>
  27
  28#include <asm/mach-jz4740/jz4740_nand.h>
  29
  30#define JZ_REG_NAND_CTRL        0x50
  31#define JZ_REG_NAND_ECC_CTRL    0x100
  32#define JZ_REG_NAND_DATA        0x104
  33#define JZ_REG_NAND_PAR0        0x108
  34#define JZ_REG_NAND_PAR1        0x10C
  35#define JZ_REG_NAND_PAR2        0x110
  36#define JZ_REG_NAND_IRQ_STAT    0x114
  37#define JZ_REG_NAND_IRQ_CTRL    0x118
  38#define JZ_REG_NAND_ERR(x)      (0x11C + ((x) << 2))
  39
  40#define JZ_NAND_ECC_CTRL_PAR_READY      BIT(4)
  41#define JZ_NAND_ECC_CTRL_ENCODING       BIT(3)
  42#define JZ_NAND_ECC_CTRL_RS             BIT(2)
  43#define JZ_NAND_ECC_CTRL_RESET          BIT(1)
  44#define JZ_NAND_ECC_CTRL_ENABLE         BIT(0)
  45
  46#define JZ_NAND_STATUS_ERR_COUNT        (BIT(31) | BIT(30) | BIT(29))
  47#define JZ_NAND_STATUS_PAD_FINISH       BIT(4)
  48#define JZ_NAND_STATUS_DEC_FINISH       BIT(3)
  49#define JZ_NAND_STATUS_ENC_FINISH       BIT(2)
  50#define JZ_NAND_STATUS_UNCOR_ERROR      BIT(1)
  51#define JZ_NAND_STATUS_ERROR            BIT(0)
  52
  53#define JZ_NAND_CTRL_ENABLE_CHIP(x) BIT((x) << 1)
  54#define JZ_NAND_CTRL_ASSERT_CHIP(x) BIT(((x) << 1) + 1)
  55#define JZ_NAND_CTRL_ASSERT_CHIP_MASK 0xaa
  56
  57#define JZ_NAND_MEM_CMD_OFFSET 0x08000
  58#define JZ_NAND_MEM_ADDR_OFFSET 0x10000
  59
  60struct jz_nand {
  61        struct mtd_info mtd;
  62        struct nand_chip chip;
  63        void __iomem *base;
  64        struct resource *mem;
  65
  66        unsigned char banks[JZ_NAND_NUM_BANKS];
  67        void __iomem *bank_base[JZ_NAND_NUM_BANKS];
  68        struct resource *bank_mem[JZ_NAND_NUM_BANKS];
  69
  70        int selected_bank;
  71
  72        struct jz_nand_platform_data *pdata;
  73        bool is_reading;
  74};
  75
  76static inline struct jz_nand *mtd_to_jz_nand(struct mtd_info *mtd)
  77{
  78        return container_of(mtd, struct jz_nand, mtd);
  79}
  80
  81static void jz_nand_select_chip(struct mtd_info *mtd, int chipnr)
  82{
  83        struct jz_nand *nand = mtd_to_jz_nand(mtd);
  84        struct nand_chip *chip = mtd->priv;
  85        uint32_t ctrl;
  86        int banknr;
  87
  88        ctrl = readl(nand->base + JZ_REG_NAND_CTRL);
  89        ctrl &= ~JZ_NAND_CTRL_ASSERT_CHIP_MASK;
  90
  91        if (chipnr == -1) {
  92                banknr = -1;
  93        } else {
  94                banknr = nand->banks[chipnr] - 1;
  95                chip->IO_ADDR_R = nand->bank_base[banknr];
  96                chip->IO_ADDR_W = nand->bank_base[banknr];
  97        }
  98        writel(ctrl, nand->base + JZ_REG_NAND_CTRL);
  99
 100        nand->selected_bank = banknr;
 101}
 102
 103static void jz_nand_cmd_ctrl(struct mtd_info *mtd, int dat, unsigned int ctrl)
 104{
 105        struct jz_nand *nand = mtd_to_jz_nand(mtd);
 106        struct nand_chip *chip = mtd->priv;
 107        uint32_t reg;
 108        void __iomem *bank_base = nand->bank_base[nand->selected_bank];
 109
 110        BUG_ON(nand->selected_bank < 0);
 111
 112        if (ctrl & NAND_CTRL_CHANGE) {
 113                BUG_ON((ctrl & NAND_ALE) && (ctrl & NAND_CLE));
 114                if (ctrl & NAND_ALE)
 115                        bank_base += JZ_NAND_MEM_ADDR_OFFSET;
 116                else if (ctrl & NAND_CLE)
 117                        bank_base += JZ_NAND_MEM_CMD_OFFSET;
 118                chip->IO_ADDR_W = bank_base;
 119
 120                reg = readl(nand->base + JZ_REG_NAND_CTRL);
 121                if (ctrl & NAND_NCE)
 122                        reg |= JZ_NAND_CTRL_ASSERT_CHIP(nand->selected_bank);
 123                else
 124                        reg &= ~JZ_NAND_CTRL_ASSERT_CHIP(nand->selected_bank);
 125                writel(reg, nand->base + JZ_REG_NAND_CTRL);
 126        }
 127        if (dat != NAND_CMD_NONE)
 128                writeb(dat, chip->IO_ADDR_W);
 129}
 130
 131static int jz_nand_dev_ready(struct mtd_info *mtd)
 132{
 133        struct jz_nand *nand = mtd_to_jz_nand(mtd);
 134        return gpio_get_value_cansleep(nand->pdata->busy_gpio);
 135}
 136
 137static void jz_nand_hwctl(struct mtd_info *mtd, int mode)
 138{
 139        struct jz_nand *nand = mtd_to_jz_nand(mtd);
 140        uint32_t reg;
 141
 142        writel(0, nand->base + JZ_REG_NAND_IRQ_STAT);
 143        reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
 144
 145        reg |= JZ_NAND_ECC_CTRL_RESET;
 146        reg |= JZ_NAND_ECC_CTRL_ENABLE;
 147        reg |= JZ_NAND_ECC_CTRL_RS;
 148
 149        switch (mode) {
 150        case NAND_ECC_READ:
 151                reg &= ~JZ_NAND_ECC_CTRL_ENCODING;
 152                nand->is_reading = true;
 153                break;
 154        case NAND_ECC_WRITE:
 155                reg |= JZ_NAND_ECC_CTRL_ENCODING;
 156                nand->is_reading = false;
 157                break;
 158        default:
 159                break;
 160        }
 161
 162        writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL);
 163}
 164
 165static int jz_nand_calculate_ecc_rs(struct mtd_info *mtd, const uint8_t *dat,
 166        uint8_t *ecc_code)
 167{
 168        struct jz_nand *nand = mtd_to_jz_nand(mtd);
 169        uint32_t reg, status;
 170        int i;
 171        unsigned int timeout = 1000;
 172        static uint8_t empty_block_ecc[] = {0xcd, 0x9d, 0x90, 0x58, 0xf4,
 173                                                0x8b, 0xff, 0xb7, 0x6f};
 174
 175        if (nand->is_reading)
 176                return 0;
 177
 178        do {
 179                status = readl(nand->base + JZ_REG_NAND_IRQ_STAT);
 180        } while (!(status & JZ_NAND_STATUS_ENC_FINISH) && --timeout);
 181
 182        if (timeout == 0)
 183            return -1;
 184
 185        reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
 186        reg &= ~JZ_NAND_ECC_CTRL_ENABLE;
 187        writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL);
 188
 189        for (i = 0; i < 9; ++i)
 190                ecc_code[i] = readb(nand->base + JZ_REG_NAND_PAR0 + i);
 191
 192        /* If the written data is completly 0xff, we also want to write 0xff as
 193         * ecc, otherwise we will get in trouble when doing subpage writes. */
 194        if (memcmp(ecc_code, empty_block_ecc, 9) == 0)
 195                memset(ecc_code, 0xff, 9);
 196
 197        return 0;
 198}
 199
 200static void jz_nand_correct_data(uint8_t *dat, int index, int mask)
 201{
 202        int offset = index & 0x7;
 203        uint16_t data;
 204
 205        index += (index >> 3);
 206
 207        data = dat[index];
 208        data |= dat[index+1] << 8;
 209
 210        mask ^= (data >> offset) & 0x1ff;
 211        data &= ~(0x1ff << offset);
 212        data |= (mask << offset);
 213
 214        dat[index] = data & 0xff;
 215        dat[index+1] = (data >> 8) & 0xff;
 216}
 217
 218static int jz_nand_correct_ecc_rs(struct mtd_info *mtd, uint8_t *dat,
 219        uint8_t *read_ecc, uint8_t *calc_ecc)
 220{
 221        struct jz_nand *nand = mtd_to_jz_nand(mtd);
 222        int i, error_count, index;
 223        uint32_t reg, status, error;
 224        uint32_t t;
 225        unsigned int timeout = 1000;
 226
 227        t = read_ecc[0];
 228
 229        if (t == 0xff) {
 230                for (i = 1; i < 9; ++i)
 231                        t &= read_ecc[i];
 232
 233                t &= dat[0];
 234                t &= dat[nand->chip.ecc.size / 2];
 235                t &= dat[nand->chip.ecc.size - 1];
 236
 237                if (t == 0xff) {
 238                        for (i = 1; i < nand->chip.ecc.size - 1; ++i)
 239                                t &= dat[i];
 240                        if (t == 0xff)
 241                                return 0;
 242                }
 243        }
 244
 245        for (i = 0; i < 9; ++i)
 246                writeb(read_ecc[i], nand->base + JZ_REG_NAND_PAR0 + i);
 247
 248        reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
 249        reg |= JZ_NAND_ECC_CTRL_PAR_READY;
 250        writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL);
 251
 252        do {
 253                status = readl(nand->base + JZ_REG_NAND_IRQ_STAT);
 254        } while (!(status & JZ_NAND_STATUS_DEC_FINISH) && --timeout);
 255
 256        if (timeout == 0)
 257            return -1;
 258
 259        reg = readl(nand->base + JZ_REG_NAND_ECC_CTRL);
 260        reg &= ~JZ_NAND_ECC_CTRL_ENABLE;
 261        writel(reg, nand->base + JZ_REG_NAND_ECC_CTRL);
 262
 263        if (status & JZ_NAND_STATUS_ERROR) {
 264                if (status & JZ_NAND_STATUS_UNCOR_ERROR)
 265                        return -1;
 266
 267                error_count = (status & JZ_NAND_STATUS_ERR_COUNT) >> 29;
 268
 269                for (i = 0; i < error_count; ++i) {
 270                        error = readl(nand->base + JZ_REG_NAND_ERR(i));
 271                        index = ((error >> 16) & 0x1ff) - 1;
 272                        if (index >= 0 && index < 512)
 273                                jz_nand_correct_data(dat, index, error & 0x1ff);
 274                }
 275
 276                return error_count;
 277        }
 278
 279        return 0;
 280}
 281
 282static int jz_nand_ioremap_resource(struct platform_device *pdev,
 283        const char *name, struct resource **res, void *__iomem *base)
 284{
 285        int ret;
 286
 287        *res = platform_get_resource_byname(pdev, IORESOURCE_MEM, name);
 288        if (!*res) {
 289                dev_err(&pdev->dev, "Failed to get platform %s memory\n", name);
 290                ret = -ENXIO;
 291                goto err;
 292        }
 293
 294        *res = request_mem_region((*res)->start, resource_size(*res),
 295                                pdev->name);
 296        if (!*res) {
 297                dev_err(&pdev->dev, "Failed to request %s memory region\n", name);
 298                ret = -EBUSY;
 299                goto err;
 300        }
 301
 302        *base = ioremap((*res)->start, resource_size(*res));
 303        if (!*base) {
 304                dev_err(&pdev->dev, "Failed to ioremap %s memory region\n", name);
 305                ret = -EBUSY;
 306                goto err_release_mem;
 307        }
 308
 309        return 0;
 310
 311err_release_mem:
 312        release_mem_region((*res)->start, resource_size(*res));
 313err:
 314        *res = NULL;
 315        *base = NULL;
 316        return ret;
 317}
 318
 319static inline void jz_nand_iounmap_resource(struct resource *res,
 320                                            void __iomem *base)
 321{
 322        iounmap(base);
 323        release_mem_region(res->start, resource_size(res));
 324}
 325
 326static int jz_nand_detect_bank(struct platform_device *pdev,
 327                               struct jz_nand *nand, unsigned char bank,
 328                               size_t chipnr, uint8_t *nand_maf_id,
 329                               uint8_t *nand_dev_id)
 330{
 331        int ret;
 332        int gpio;
 333        char gpio_name[9];
 334        char res_name[6];
 335        uint32_t ctrl;
 336        struct mtd_info *mtd = &nand->mtd;
 337        struct nand_chip *chip = &nand->chip;
 338
 339        /* Request GPIO port. */
 340        gpio = JZ_GPIO_MEM_CS0 + bank - 1;
 341        sprintf(gpio_name, "NAND CS%d", bank);
 342        ret = gpio_request(gpio, gpio_name);
 343        if (ret) {
 344                dev_warn(&pdev->dev,
 345                        "Failed to request %s gpio %d: %d\n",
 346                        gpio_name, gpio, ret);
 347                goto notfound_gpio;
 348        }
 349
 350        /* Request I/O resource. */
 351        sprintf(res_name, "bank%d", bank);
 352        ret = jz_nand_ioremap_resource(pdev, res_name,
 353                                        &nand->bank_mem[bank - 1],
 354                                        &nand->bank_base[bank - 1]);
 355        if (ret)
 356                goto notfound_resource;
 357
 358        /* Enable chip in bank. */
 359        jz_gpio_set_function(gpio, JZ_GPIO_FUNC_MEM_CS0);
 360        ctrl = readl(nand->base + JZ_REG_NAND_CTRL);
 361        ctrl |= JZ_NAND_CTRL_ENABLE_CHIP(bank - 1);
 362        writel(ctrl, nand->base + JZ_REG_NAND_CTRL);
 363
 364        if (chipnr == 0) {
 365                /* Detect first chip. */
 366                ret = nand_scan_ident(mtd, 1, NULL);
 367                if (ret)
 368                        goto notfound_id;
 369
 370                /* Retrieve the IDs from the first chip. */
 371                chip->select_chip(mtd, 0);
 372                chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
 373                chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
 374                *nand_maf_id = chip->read_byte(mtd);
 375                *nand_dev_id = chip->read_byte(mtd);
 376        } else {
 377                /* Detect additional chip. */
 378                chip->select_chip(mtd, chipnr);
 379                chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
 380                chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
 381                if (*nand_maf_id != chip->read_byte(mtd)
 382                 || *nand_dev_id != chip->read_byte(mtd)) {
 383                        ret = -ENODEV;
 384                        goto notfound_id;
 385                }
 386
 387                /* Update size of the MTD. */
 388                chip->numchips++;
 389                mtd->size += chip->chipsize;
 390        }
 391
 392        dev_info(&pdev->dev, "Found chip %i on bank %i\n", chipnr, bank);
 393        return 0;
 394
 395notfound_id:
 396        dev_info(&pdev->dev, "No chip found on bank %i\n", bank);
 397        ctrl &= ~(JZ_NAND_CTRL_ENABLE_CHIP(bank - 1));
 398        writel(ctrl, nand->base + JZ_REG_NAND_CTRL);
 399        jz_gpio_set_function(gpio, JZ_GPIO_FUNC_NONE);
 400        jz_nand_iounmap_resource(nand->bank_mem[bank - 1],
 401                                 nand->bank_base[bank - 1]);
 402notfound_resource:
 403        gpio_free(gpio);
 404notfound_gpio:
 405        return ret;
 406}
 407
 408static int jz_nand_probe(struct platform_device *pdev)
 409{
 410        int ret;
 411        struct jz_nand *nand;
 412        struct nand_chip *chip;
 413        struct mtd_info *mtd;
 414        struct jz_nand_platform_data *pdata = pdev->dev.platform_data;
 415        size_t chipnr, bank_idx;
 416        uint8_t nand_maf_id = 0, nand_dev_id = 0;
 417
 418        nand = kzalloc(sizeof(*nand), GFP_KERNEL);
 419        if (!nand) {
 420                dev_err(&pdev->dev, "Failed to allocate device structure.\n");
 421                return -ENOMEM;
 422        }
 423
 424        ret = jz_nand_ioremap_resource(pdev, "mmio", &nand->mem, &nand->base);
 425        if (ret)
 426                goto err_free;
 427
 428        if (pdata && gpio_is_valid(pdata->busy_gpio)) {
 429                ret = gpio_request(pdata->busy_gpio, "NAND busy pin");
 430                if (ret) {
 431                        dev_err(&pdev->dev,
 432                                "Failed to request busy gpio %d: %d\n",
 433                                pdata->busy_gpio, ret);
 434                        goto err_iounmap_mmio;
 435                }
 436        }
 437
 438        mtd             = &nand->mtd;
 439        chip            = &nand->chip;
 440        mtd->priv       = chip;
 441        mtd->owner      = THIS_MODULE;
 442        mtd->name       = "jz4740-nand";
 443
 444        chip->ecc.hwctl         = jz_nand_hwctl;
 445        chip->ecc.calculate     = jz_nand_calculate_ecc_rs;
 446        chip->ecc.correct       = jz_nand_correct_ecc_rs;
 447        chip->ecc.mode          = NAND_ECC_HW_OOB_FIRST;
 448        chip->ecc.size          = 512;
 449        chip->ecc.bytes         = 9;
 450        chip->ecc.strength      = 4;
 451
 452        if (pdata)
 453                chip->ecc.layout = pdata->ecc_layout;
 454
 455        chip->chip_delay = 50;
 456        chip->cmd_ctrl = jz_nand_cmd_ctrl;
 457        chip->select_chip = jz_nand_select_chip;
 458
 459        if (pdata && gpio_is_valid(pdata->busy_gpio))
 460                chip->dev_ready = jz_nand_dev_ready;
 461
 462        nand->pdata = pdata;
 463        platform_set_drvdata(pdev, nand);
 464
 465        /* We are going to autodetect NAND chips in the banks specified in the
 466         * platform data. Although nand_scan_ident() can detect multiple chips,
 467         * it requires those chips to be numbered consecuitively, which is not
 468         * always the case for external memory banks. And a fixed chip-to-bank
 469         * mapping is not practical either, since for example Dingoo units
 470         * produced at different times have NAND chips in different banks.
 471         */
 472        chipnr = 0;
 473        for (bank_idx = 0; bank_idx < JZ_NAND_NUM_BANKS; bank_idx++) {
 474                unsigned char bank;
 475
 476                /* If there is no platform data, look for NAND in bank 1,
 477                 * which is the most likely bank since it is the only one
 478                 * that can be booted from.
 479                 */
 480                bank = pdata ? pdata->banks[bank_idx] : bank_idx ^ 1;
 481                if (bank == 0)
 482                        break;
 483                if (bank > JZ_NAND_NUM_BANKS) {
 484                        dev_warn(&pdev->dev,
 485                                "Skipping non-existing bank: %d\n", bank);
 486                        continue;
 487                }
 488                /* The detection routine will directly or indirectly call
 489                 * jz_nand_select_chip(), so nand->banks has to contain the
 490                 * bank we're checking.
 491                 */
 492                nand->banks[chipnr] = bank;
 493                if (jz_nand_detect_bank(pdev, nand, bank, chipnr,
 494                                        &nand_maf_id, &nand_dev_id) == 0)
 495                        chipnr++;
 496                else
 497                        nand->banks[chipnr] = 0;
 498        }
 499        if (chipnr == 0) {
 500                dev_err(&pdev->dev, "No NAND chips found\n");
 501                goto err_gpio_busy;
 502        }
 503
 504        if (pdata && pdata->ident_callback) {
 505                pdata->ident_callback(pdev, chip, &pdata->partitions,
 506                                        &pdata->num_partitions);
 507        }
 508
 509        ret = nand_scan_tail(mtd);
 510        if (ret) {
 511                dev_err(&pdev->dev,  "Failed to scan NAND\n");
 512                goto err_unclaim_banks;
 513        }
 514
 515        ret = mtd_device_parse_register(mtd, NULL, NULL,
 516                                        pdata ? pdata->partitions : NULL,
 517                                        pdata ? pdata->num_partitions : 0);
 518
 519        if (ret) {
 520                dev_err(&pdev->dev, "Failed to add mtd device\n");
 521                goto err_nand_release;
 522        }
 523
 524        dev_info(&pdev->dev, "Successfully registered JZ4740 NAND driver\n");
 525
 526        return 0;
 527
 528err_nand_release:
 529        nand_release(mtd);
 530err_unclaim_banks:
 531        while (chipnr--) {
 532                unsigned char bank = nand->banks[chipnr];
 533                gpio_free(JZ_GPIO_MEM_CS0 + bank - 1);
 534                jz_nand_iounmap_resource(nand->bank_mem[bank - 1],
 535                                         nand->bank_base[bank - 1]);
 536        }
 537        writel(0, nand->base + JZ_REG_NAND_CTRL);
 538err_gpio_busy:
 539        if (pdata && gpio_is_valid(pdata->busy_gpio))
 540                gpio_free(pdata->busy_gpio);
 541        platform_set_drvdata(pdev, NULL);
 542err_iounmap_mmio:
 543        jz_nand_iounmap_resource(nand->mem, nand->base);
 544err_free:
 545        kfree(nand);
 546        return ret;
 547}
 548
 549static int jz_nand_remove(struct platform_device *pdev)
 550{
 551        struct jz_nand *nand = platform_get_drvdata(pdev);
 552        struct jz_nand_platform_data *pdata = pdev->dev.platform_data;
 553        size_t i;
 554
 555        nand_release(&nand->mtd);
 556
 557        /* Deassert and disable all chips */
 558        writel(0, nand->base + JZ_REG_NAND_CTRL);
 559
 560        for (i = 0; i < JZ_NAND_NUM_BANKS; ++i) {
 561                unsigned char bank = nand->banks[i];
 562                if (bank != 0) {
 563                        jz_nand_iounmap_resource(nand->bank_mem[bank - 1],
 564                                                 nand->bank_base[bank - 1]);
 565                        gpio_free(JZ_GPIO_MEM_CS0 + bank - 1);
 566                }
 567        }
 568        if (pdata && gpio_is_valid(pdata->busy_gpio))
 569                gpio_free(pdata->busy_gpio);
 570
 571        jz_nand_iounmap_resource(nand->mem, nand->base);
 572
 573        platform_set_drvdata(pdev, NULL);
 574        kfree(nand);
 575
 576        return 0;
 577}
 578
 579static struct platform_driver jz_nand_driver = {
 580        .probe = jz_nand_probe,
 581        .remove = jz_nand_remove,
 582        .driver = {
 583                .name = "jz4740-nand",
 584                .owner = THIS_MODULE,
 585        },
 586};
 587
 588module_platform_driver(jz_nand_driver);
 589
 590MODULE_LICENSE("GPL");
 591MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
 592MODULE_DESCRIPTION("NAND controller driver for JZ4740 SoC");
 593MODULE_ALIAS("platform:jz4740-nand");
 594
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.