#include <crypto/ctr.h>
 #include <crypto/gcm.h>
 #include <crypto/sha.h>
+#include <crypto/rng.h>
 #include <crypto/scatterwalk.h>
 #include <crypto/skcipher.h>
 #include <crypto/internal/aead.h>
+#include <crypto/internal/rng.h>
 #include <crypto/internal/skcipher.h>
 #include "crypto4xx_reg_def.h"
 #include "crypto4xx_core.h"
                        rc = crypto_register_ahash(&alg->alg.u.hash);
                        break;
 
+               case CRYPTO_ALG_TYPE_RNG:
+                       rc = crypto_register_rng(&alg->alg.u.rng);
+                       break;
+
                default:
                        rc = crypto_register_skcipher(&alg->alg.u.cipher);
                        break;
                        crypto_unregister_aead(&alg->alg.u.aead);
                        break;
 
+               case CRYPTO_ALG_TYPE_RNG:
+                       crypto_unregister_rng(&alg->alg.u.rng);
+                       break;
+
                default:
                        crypto_unregister_skcipher(&alg->alg.u.cipher);
                }
                PPC4XX_TMO_ERR_INT);
 }
 
+static int ppc4xx_prng_data_read(struct crypto4xx_device *dev,
+                                u8 *data, unsigned int max)
+{
+       unsigned int i, curr = 0;
+       u32 val[2];
+
+       do {
+               /* trigger PRN generation */
+               writel(PPC4XX_PRNG_CTRL_AUTO_EN,
+                      dev->ce_base + CRYPTO4XX_PRNG_CTRL);
+
+               for (i = 0; i < 1024; i++) {
+                       /* usually 19 iterations are enough */
+                       if ((readl(dev->ce_base + CRYPTO4XX_PRNG_STAT) &
+                            CRYPTO4XX_PRNG_STAT_BUSY))
+                               continue;
+
+                       val[0] = readl_be(dev->ce_base + CRYPTO4XX_PRNG_RES_0);
+                       val[1] = readl_be(dev->ce_base + CRYPTO4XX_PRNG_RES_1);
+                       break;
+               }
+               if (i == 1024)
+                       return -ETIMEDOUT;
+
+               if ((max - curr) >= 8) {
+                       memcpy(data, &val, 8);
+                       data += 8;
+                       curr += 8;
+               } else {
+                       /* copy only remaining bytes */
+                       memcpy(data, &val, max - curr);
+                       break;
+               }
+       } while (curr < max);
+
+       return curr;
+}
+
+static int crypto4xx_prng_generate(struct crypto_rng *tfm,
+                                  const u8 *src, unsigned int slen,
+                                  u8 *dstn, unsigned int dlen)
+{
+       struct rng_alg *alg = crypto_rng_alg(tfm);
+       struct crypto4xx_alg *amcc_alg;
+       struct crypto4xx_device *dev;
+       int ret;
+
+       amcc_alg = container_of(alg, struct crypto4xx_alg, alg.u.rng);
+       dev = amcc_alg->dev;
+
+       mutex_lock(&dev->core_dev->rng_lock);
+       ret = ppc4xx_prng_data_read(dev, dstn, dlen);
+       mutex_unlock(&dev->core_dev->rng_lock);
+       return ret;
+}
+
+
+static int crypto4xx_prng_seed(struct crypto_rng *tfm, const u8 *seed,
+                       unsigned int slen)
+{
+       return 0;
+}
+
 /**
  * Supported Crypto Algorithms
  */
                        .cra_module     = THIS_MODULE,
                },
        } },
+       { .type = CRYPTO_ALG_TYPE_RNG, .u.rng = {
+               .base = {
+                       .cra_name               = "stdrng",
+                       .cra_driver_name        = "crypto4xx_rng",
+                       .cra_priority           = 300,
+                       .cra_ctxsize            = 0,
+                       .cra_module             = THIS_MODULE,
+               },
+               .generate               = crypto4xx_prng_generate,
+               .seed                   = crypto4xx_prng_seed,
+               .seedsize               = 0,
+       } },
 };
 
 /**
        core_dev->dev->core_dev = core_dev;
        core_dev->dev->is_revb = is_revb;
        core_dev->device = dev;
+       mutex_init(&core_dev->rng_lock);
        spin_lock_init(&core_dev->lock);
        INIT_LIST_HEAD(&core_dev->dev->alg_list);
        ratelimit_default_init(&core_dev->dev->aead_ratelimit);
        tasklet_kill(&core_dev->tasklet);
        /* Un-register with Linux CryptoAPI */
        crypto4xx_unregister_alg(core_dev->dev);
+       mutex_destroy(&core_dev->rng_lock);
        /* Free all allocated memory */
        crypto4xx_stop_all(core_dev);